这里追踪 相机打开流程,从 Java API 到 camera service,可以参照下面的核心类,进行追踪
1 openCamera
frameworks/base/core/java/android/hardware/camera2/CameraManager.java # openCamera
打开与给定ID的相机的连接。
下面是一些注意点,简单看一下:
使用{@link #getCameraIdList}来获取可用相机设备的列表。请注意,即使列出了id,如果设备在调用{@ link# getCameraIdList}和{@ link# openCamera}之间断开连接,或者如果更高优先级的相机API客户端开始使用相机设备,则打开可能会失败。
一旦相机成功打开,{@link CameraDevice。StateCallback#onOpened}将与新打开的{@link CameraDevice}一起调用。然后可以通过调用{@link CameraDevice#createCaptureSession}和{@link CameraDevice#createCaptureRequest}来设置相机设备进行操作。
在API级别30之前,当应用程序尝试打开多个不同id的{@link CameraDevice}并且设备不支持打开这样的组合时,{@link #openCamera}将失败并抛出{@link CameraAccessException}或一个或多个已打开的{@link CameraDevice}将断开连接并接收{@link android.硬件。camera2.CameraDevice.StateCallback # onDisconnected}的回调函数。哪种行为会发生取决于设备实现,并且在不同的设备上可能会有所不同。从API级别30开始,如果设备不支持正在打开的相机组合,则可以保证{@link #openCamera}调用将失败,并且现有的{@link CameraDevice}都不会断开连接。
由于相机设备将被异步打开,任何在返回的CameraDevice实例上完成的异步操作将被排队,直到设备启动完成和回调的{@link CameraDevice.StateCallback#onOpened onOpened}方法被调用。然后按顺序处理挂起的操作。
* @param cameraId
* The unique identifier of the camera device to open
* @param callback
* The callback which is invoked once the camera is opened
* @param handler
* The handler on which the callback should be invoked, or
* {
@code null} to use the current thread's {
@link android.os.Looper looper}.
// Open a connection to a camera with the given ID.
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
USE_CALLING_UID);
}
2 追踪 openCamera 具体做了哪些事情
我们重点看一下 打开相机的过程做了哪些事情:
2.1 openCameraForUid
可以看到 openCamera指定用于权限等验证的UID为 USE_CALLING_UID,用来通过权限认证
/**
* Open a connection to a camera with the given ID, on behalf of another application
* specified by clientUid.
代表由clientUid指定的另一个应用程序,打开给定ID的相机的连接。
*
* <p>The behavior of this method matches that of {@link #openCamera}, except that it allows
* the caller to specify the UID to use for permission/etc verification. This can only be
* done by services trusted by the camera subsystem to act on behalf of applications and
* to forward the real UID.</p>
*
* @param clientUid
* The UID of the application on whose behalf the camera is being opened.
* Must be USE_CALLING_UID unless the caller is a trusted service.
*
* @hide
*/
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid) throws CameraAccessException {
openCameraForUid(cameraId, callback, executor, clientUid, /*oomScoreOffset*/0,
shouldOverrideToPortrait(mContext));
}
2.2 openCameraDeviceUserAsync
frameworks/base/core/java/android/hardware/camera2/CameraManager.java # openCameraDeviceUserAsync
真正的逻辑在这里开始
/**
* Helper for opening a connection to a camera with the given ID.
*
* @param cameraId The unique identifier of the camera device to open
* @param callback The callback for the camera. Must not be null.
* @param executor The executor to invoke the callback with. Must not be null.
* @param uid The UID of the application actually opening the camera.
* Must be USE_CALLING_UID unless the caller is a service
* that is trusted to open the device on behalf of an
* application and to forward the real UID.
*
* @throws CameraAccessException if the camera is disabled by device policy,
* too many camera devices are already open, or the cameraId does not match
* any currently available camera device.
*
* @throws SecurityException if the application does not have permission to
* access the camera
* @throws IllegalArgumentException if callback or handler is null.
* @return A handle to the newly-created camera device.
*
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Executor executor, final int uid,
final int oomScoreOffset, boolean overrideToPortrait) throws CameraAccessException {
// 返回的信息,包括是否有强制并发流的标志,int 类型的camera id, display size, 可能得 多分辨率流配置
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
// 返回 getPhysicalCameraIds()返回的physicalCameraId作为key,
// getCameraCharacteristics(physicalCameraId)返回的 CameraCharacteristics 作为 value的 map
Map<String, CameraCharacteristics> physicalIdsToChars =
getPhysicalIdToCharsMap(characteristics);
synchronized (mLock) {
ICameraDeviceUser cameraUser