广东手机网站制作价格,贵州讯玛网站建设,做网站设计赚不赚钱,网站没有权重相机可用性变化监听及流程分析
一、接口说明
相机可用性变化监听可以通过CameraManager中的接口registerAvailabilityCallback()来设置回调#xff0c;接口如下#xff1a;
/**
*注册一个回调以获得有关相机设备可用性的通知。
*
*p再次注册相同的回调将用提供…相机可用性变化监听及流程分析
一、接口说明
相机可用性变化监听可以通过CameraManager中的接口registerAvailabilityCallback()来设置回调接口如下
/**
*注册一个回调以获得有关相机设备可用性的通知。
*
*p再次注册相同的回调将用提供的新回调替换处理程序/p
*
*p第一次注册回调时会立即调用回调并显示当前已知的所有相机设备的可用性状态/p
*
*任何相机API客户端打开相机设备时都会调用p{linkAvailabilityCallback#onCameraUnavailableString}。从API级别23开始其他相机API客户端可能仍然能够打开这样的相机设备如果它们的优先级高于相机设备的现有客户端则会逐出现有客户端。有关详细信息请参阅open/p
*
*p由于此回调将在相机服务中注册请记住在不再需要时注销它否则回调将无限期地继续接收事件并可能阻止其他资源被释放。具体来说回调将调用各个CameraManager实例的状态/p
*
*param callback 向发送相机可用性通知的新回调。
*param handler 应该调用回调的handler或者为{code null}的话使用当前线程的{linkandroid.os.Looper Looper}。
*
*如果handler为code null但当前线程没有Looper则throws IllegalArgumentException。
*/
public void registerAvailabilityCallback(NonNull AvailabilityCallback callback, Nullable Handler handler)AvailabilityCallback主要api如下 /***摄像机设备变为可用或不可用的回调。**p当不再使用相机或连接新的可移动相机时相机将可用。当某些应用程序或服务开始使用相机时或者当可移动相机断开连接时它们将不可用/p**p扩展此回调并将子类的一个实例传递给{link CameraManager#registerAvailabilityCallback}以便收到此类可用性更改的通知/p**参见#registerAvailabilityCallback*/public static abstract class AvailabilityCallback {/***一台新相机已经可以使用了。**p此方法的默认实现不执行任何操作/p**param cameraId新相机的唯一标识符。*/public void onCameraAvailable(NonNull String cameraId) {// default empty implementation}/***以前可用的相机已无法使用。**p*如果一个应用程序有一个活动的CameraDevice实例用于现在断开连接的相机该应用程序将收到link CameraDevice.StateCallback#onDisconnected disconnection error*/p**p此方法的默认实现不执行任何操作/p**param cameraId断开连接的摄像机的唯一标识符。*/public void onCameraUnavailable(NonNull String cameraId) {// default empty implementation}/***每当摄像机访问优先级更改时调用。**p通知相机访问优先级已更改相机现在可以打开。先前由于较高优先级的用户已经在使用相机而被拒绝访问相机的应用程序或者由于较高优先级用户试图打开相机而与活动相机会话断开连接的应用程序如果仍想使用相机则应尝试再次打开相机。请注意多个应用程序可能同时接收此回调并且在实践中根据确切的访问优先级和时间只有其中一个应用程序能够成功打开相机。如果多个应用程序可能同时处于恢复状态并且用户在它们之间切换焦点或者使用应用程序的当前相机在全屏和画中画PiP状态之间移动则此方法非常有用。在这种情况下摄像机可用/不可用回调将不会被调用但另一个应用程序现在可能比当前使用摄像机的应用程序具有更高的摄像机访问优先级/p**p此方法的默认实现不执行任何操作/p*/public void onCameraAccessPrioritiesChanged() {// default empty implementation}/***一台物理相机已可再次使用。**p默认情况下逻辑多摄像机的所有物理摄像机都可用因此当调用逻辑多摄像机用的{link#onCameraAvailable}时不会为逻辑多摄像机中的任何物理摄像机调用{link#onPhysicalCameraAvailable。但是如果某些特定的物理摄影机一开始就不可用则可以在link#onCameraAvailable之后调用link#onPhysicalCameraUnavailable/p**p此方法的默认实现不执行任何操作/p**param cameraId逻辑多摄像机的唯一标识符。*param physicalCameraId物理相机的唯一标识符。**请参阅#onCameraAvailable*请参阅#onPhysicalCamera不可用*/public void onPhysicalCameraAvailable(NonNull String cameraId,NonNull String physicalCameraId) {// default empty implementation}/***以前可用的物理相机已无法使用。**p默认情况下逻辑多摄像机的所有物理摄像机都可用因此当调用逻辑多摄像机用的{link#onCameraAvailable}时不会为逻辑多摄像机中的任何物理摄像机调用{link#onPhysicalCameraAvailable。如果某些特定的物理相机一开始就不可用则可以在link#onCameraAvailable之后调用link#onPhysicalCameraUnavailable/p**p此方法的默认实现不执行任何操作/p**param cameraId逻辑多摄像机的唯一标识符。*param physicalCameraId物理相机的唯一标识符。**请参阅#onCameraAvailable*请参阅#onPhysicalCameraAvailable*/public void onPhysicalCameraUnavailable(NonNull String cameraId,NonNull String physicalCameraId) {// default empty implementation}}注意这里physical camera和logical multi-camera的区别 physical camera物理摄像头对应实际的物理硬件。 logical multi-camera是在某些支持的 Android 设备上引入的一项功能它允许开发者同时使用多个摄像头来进行更高级的图像处理和功能。在逻辑多摄像头系统中多个物理摄像头可以捆绑在一起并被视为单个逻辑摄像头设备。这些物理摄像头可以包括不同的焦距、不同的传感器类型例如彩色相机和红外相机等。由于这些物理摄像头协同工作它们可以为开发者提供更丰富的功能和更灵活的图像处理能力。
二、源码调用链分析
1.回调设置的过程
\frameworks\base\core\java\android\hardware\camera2\CameraManager.java
public void registerAvailabilityCallback(NonNull AvailabilityCallback callback, Nullable Handler handler) {CameraManagerGlobal.get().registerAvailabilityCallback(callback, CameraDeviceImpl.checkAndWrapHandler(handler));
}调用到CameraManager的内部类CameraManagerGlobal的方法registerAvailabilityCallback
\frameworks\base\core\java\android\hardware\camera2\CameraManager.java
public void registerAvailabilityCallback(AvailabilityCallback callback,Executor executor) {synchronized (mLock) {/*1.连接到CameraService如果已经连接不执行任何操作。*/connectCameraServiceLocked();/*2.将设置的callback存入mCallbackMap中。mCallbackMap专门用于存储可用性回调以及执行它们的Executor。*/Executor oldExecutor mCallbackMap.put(callback, executor);// For new callbacks, provide initial availability informationif (oldExecutor null) {/*3.如果oldExecutor为空说明是第一次设置该可用性回调。将当前已知的所有相机的状态触发设置的callback回调以便使监听者了解当前所有相机状态。*/updateCallbackLocked(callback, executor);}// If not connected to camera service, schedule a reconnect to camera service.if (mCameraService null) {/*4.如果mCameraService为空说明连接CameraService失败计划一次新的重连尝试。*/scheduleCameraServiceReconnectionLocked();}}
} 到这里设置的可用性回调已经被存储到mCallbackMap当中设置回调的流程完毕后续相机状态变化触发回调时将遍历mCallbackMap取出callback并执行相应的回调方法。 说一点题外话这里可以关注一下Google对CameraManager类的设计该类整体比较简单主要就是对外暴露方法的定义以及CameraManagerGlobal类的定义CameraManager对外暴露的方法基本上都是调用静态内部类CameraManagerGlobal当中的对应实现。CameraManagerGlobal类私有化了构造方法其实例化的方法封装到了get方法当中实现了一个单例。这样做的主要目的是确保一个进程中CameraManagerGlobal只被实例化一次从而与CameraService的AIDL连接也只会建立一次。从该类的注释中可以看出。“每个进程的全局CameraManager实例用于持有到CameraService的连接并将相机可用性通知分发给api注册的回调”。 /*** A per-process global camera manager instance, to retain a connection to the camera service,
* and to distribute camera availability notices to API-registered callbacks
*/
private static final class CameraManagerGlobal extends ICameraServiceListener.Stub implements IBinder.DeathRecipient {/*略*/}2.回调触发的过程
这里主要关注回调AvailabilityCallback中的onCameraAvailable和onCameraUnavailable方法的触发。我将从这两个方法最终被调用的地方开始往前梳理调用链。
发现方法最终被调用的地方只有一个即为CameraManager的内部类CameraManagerGlobal的内部类中的private方法postSingleUpdate:
\frameworks\base\core\java\android\hardware\camera2\CameraManager.java
private void postSingleUpdate(final AvailabilityCallback callback,final Executor executor,final String id, final String physicalId, final int status) {/*略*/}继续分析发现调用postSingleUpdate的方法的地方为CameraManager的内部类CameraManagerGlobal中的另外3个private方法
\frameworks\base\core\java\android\hardware\camera2\CameraManager.java
private void updateCallbackLocked(AvailabilityCallback callback,Executor executor) {/*略*/}
private void onStatusChangedLocked(int status, String id) {/*略*/}
private void onPhysicalCameraStatusChangedLocked(int status, String id, String physicalId) {/*略*/}updateCallbackLocked方法只在注册回调时调用忽略。关注onStatusChangedLocked和onPhysicalCameraStatusChangedLocked两个方法从名称上可以看出这两个方法的用意这里我们主要关注onStatusChangedLocked方法的调用。
发现调用onStatusChangedLocked方法的均为CameraManager的内部类CameraManagerGlobal中方法包括以下4个方法
\frameworks\base\core\java\android\hardware\camera2\CameraManager.java
private void connectCameraServiceLocked() {/*略*/}
public String[] getCameraIdListNoLazy() {/*略*/}
Override
public void onStatusChanged(int status, String cameraId) throws RemoteException {/*略*/}
public void binderDied() {/*略*/}其中onStatusChanged方法重写自CameraManagerGlobal实现的ICameraServiceListener.Stub接口即该方法为相机框架中4个关键AIDL文件之一的CameraServiceListener.aidl中定义的方法通过CameraServiceListener.aidlCameraService可以调用CameraManager中的方法。相机框架4个关键AIDL文件包括ICameraService.aidl、ICameraDeviceCallback.aidl、ICameraDeviceUser.aidl、ICameraServiceListener.aidl
所以现在直接追溯到CameraService中通过AIDL调用onStatusChanged的地方:
void CameraService::updateStatus(StatusInternal status, const String8 cameraId,std::initializer_listStatusInternalrejectSourceStates) {/*……略……*/for (auto listener : mListenerList) {/*……略……*/listener-getListener()-onStatusChanged(mapToInterface(status),String16(cameraId));/*……略……*/}/*……略……*/
}未完待续……