• 虚拟摄像头之八: 从 Camera api2 角度看摄像头框架


    前言

    随着Android系统的不断升级,相机子系统框架也在不断进化,由最初的API1和HAL1到现在的API2和HAL3,由最初简单的拍照,录制到现在的连拍,AI人脸识别;可以说是架构上变动最大最频繁的子系统。

    如果您希望通过相机 HAL1 支持性能略低的前置摄像头,并通过相机 HAL3 支持更为高级的后置摄像头,Android 相机服务还支持同时实现两种 HAL1 和 HAL3,
    Android 的相机硬件抽象层 (HAL) 可将 Camera Api v2 中较高级别的相机框架 API 连接到底层的相机驱动程序和硬件,相机 HAL 则可提供用于实现您的这些组件版本的接口。

    在前面的文章中描述 Android 系统 android.hardware.Camera (api1) 是如何通过JNI接口调用 libcamera_client.so库、管理系统摄像头; 本篇从 CameraManager 看如何使用 android.hardware.Camera2 接口框架来使用相机,Android 应用中涉及到相机类如下:

    Android Camera-Camera2

    CameraManager 相机系统服务,用于管理和连接相机设备

    CameraDevice 相机设备类,和Camera1中的Camera同级

    CameraCharacteristics 主要用于获取相机信息,内部携带大量的相机信息,包含摄像头的正反(LENS_FACING)、AE模式、AF模式等,
    和Camera1中的Camera.Parameters类似

    CaptureRequest 相机捕获图像的设置请求,包含传感器,镜头,闪光灯等

    CaptureRequest.Builder CaptureRequest的构造器,使用Builder模式,设置更加方便

    CameraCaptureSession 请求抓取相机图像帧的会话,会话的建立主要会建立起一个通道。一个CameraDevice一次只能开启一个CameraCaptureSession。
    源端是相机,另一端是 Target,Target可以是Preview,也可以是ImageReader。

    ImageReader 用于从相机打开的通道中读取需要的格式的原始图像数据,可以设置多个ImageReader。

    用户App 使用 api V2 接口、打开摄像头

    用户通过 CameraManager类 openCamera 方法打开摄像头、代码如下:

        public static final String CAMERA_SERVICE = "camera";
    
        private void openCamera(int width, int height) {
            if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {
                requestCameraPermission();
                return;
            }
            setUpCameraOutputs(width, height);
            configureTransform(width, height);
            Activity activity = getActivity();
    
            CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
            try {
                if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
                    throw new RuntimeException("Time out waiting to lock camera opening.");
                }
                manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    源码 manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler); 调用 CameraManager 类的 openCamera()方法内容如下:
    @frameworks/base/core/java/android/hardware/camera2/CameraManager.java

    @SystemService(Context.CAMERA_SERVICE)
    public final class CameraManager {
        @SuppressWarnings("unused")
        private static final int API_VERSION_1 = 1;
        private static final int API_VERSION_2 = 2;
    
        private static final int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0;
        private static final int CAMERA_TYPE_ALL = 1;
    
        private ArrayList<String> mDeviceIdList;
    
        private final Context mContext;
        private final Object mLock = new Object();
    
        public CameraManager(Context context) {
            synchronized(mLock) {
                mContext = context;
            }
        }
    
        //> 1. openCamera 方法
        @RequiresPermission(android.Manifest.permission.CAMERA)
        public void openCamera(@NonNull String cameraId,
                @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
                throws CameraAccessException {
            openCameraForUid(cameraId, callback, handler, USE_CALLING_UID);
        }
    
        //> 2 进一步调用 openCameraForUid 函数
        public void openCameraForUid(@NonNull String cameraId,
                @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler,
                int clientUid)
                throws CameraAccessException {
    
            if (cameraId == null) {
                throw new IllegalArgumentException("cameraId was null");
            } else if (callback == null) {
                throw new IllegalArgumentException("callback was null");
            } else if (handler == null) {
                if (Looper.myLooper() != null) {
                    handler = new Handler();
                } else {
                    throw new IllegalArgumentException(
                            "Handler argument is null, but no looper exists in the calling thread");
                }
            }
            if (CameraManagerGlobal.sCameraServiceDisabled) {
                throw new IllegalArgumentException("No cameras available on device");
            }
    
            openCameraDeviceUserAsync(cameraId, callback, handler, clientUid);
        }
    
        //> 3 最后调用到 openCameraDeviceUserAsync() 函数、返回 CameraDevice 抽象接口类对象
        private CameraDevice openCameraDeviceUserAsync(String cameraId,
                CameraDevice.StateCallback callback, Handler handler, final int uid)
                throws CameraAccessException {
            CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
            CameraDevice device = null;
    
            synchronized (mLock) {
    
                ICameraDeviceUser cameraUser = null;
                //> 通过 CameraDeviceImpl 获取 ICameraDeviceCallbacks 回调服务
                android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                        new android.hardware.camera2.impl.CameraDeviceImpl(
                            cameraId,
                            callback,
                            handler,
                            characteristics,
                            mContext.getApplicationInfo().targetSdkVersion);
    
                ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
                
                try {
                    //> 检查是否服务是否支持 Api V2 
                    if (supportsCamera2ApiLocked(cameraId)) {
                        //> 获取 "media.camera" 的 ICameraService 服务,
                        //> Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
                        ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
                        if (cameraService == null) {
                            throw new ServiceSpecificException(
                                ICameraService.ERROR_DISCONNECTED,
                                "Camera service is currently unavailable");
                        }
                        //> 4. 通过 cameraService服务 连接到摄像头设备
                        cameraUser = cameraService.connectDevice(callbacks, cameraId,
                                mContext.getOpPackageName(), uid);
                    } else {
                        //> 使用 api v1 版本接口
                        // Use legacy camera implementation for HAL1 devices
                        int id;
                        try {
                            id = Integer.parseInt(cameraId);
                        } catch (NumberFormatException e) {
                            throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
                                    + cameraId);
                        }
    
                        //> 使用 V1 API 连接到摄像头设备
                        Log.i(TAG, "Using legacy camera HAL.");
                        cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
                    }
    
                } catch (ServiceSpecificException e) {
                    if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
                        throw new AssertionError("Should've gone down the shim path");
                    } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
                            e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
                            e.errorCode == ICameraService.ERROR_DISABLED ||
                            e.errorCode == ICameraService.ERROR_DISCONNECTED ||
                            e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
                        // Received one of the known connection errors
                        // The remote camera device cannot be connected to, so
                        // set the local camera to the startup error state
                        deviceImpl.setRemoteFailure(e);
    
                        if (e.errorCode == ICameraService.ERROR_DISABLED ||
                                e.errorCode == ICameraService.ERROR_DISCONNECTED ||
                                e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
                            // Per API docs, these failures call onError and throw
                            throwAsPublicException(e);
                        }
                    } else {
                        // Unexpected failure - rethrow
                        throwAsPublicException(e);
                    }
                } catch (RemoteException e) {
                    // Camera service died - act as if it's a CAMERA_DISCONNECTED case
                    ServiceSpecificException sse = new ServiceSpecificException(
                        ICameraService.ERROR_DISCONNECTED,
                        "Camera service is currently unavailable");
                    deviceImpl.setRemoteFailure(sse);
                    throwAsPublicException(sse);
                }
    
                // TODO: factor out callback to be non-nested, then move setter to constructor
                // For now, calling setRemoteDevice will fire initial
                // onOpened/onUnconfigured callbacks.
                // This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
                // cameraUser dies during setup.
                deviceImpl.setRemoteDevice(cameraUser);
                device = deviceImpl;
            }
    
            return device;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148

    源码中关键部分笔者标注了注释,我们看到 supportsCamera2ApiLocked(cameraId) 检查该摄像头的api版本,此处是兼容性设计、我们只关注 API V2版本的过程,
    ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); 获取 ICameraService 服务和 ICameraDeviceUser cameraUser = cameraService.connectDevice(callbacks, cameraId, mContext.getOpPackageName(), uid); 过程,成功连接摄像头后,也即是 CameraManager::openCamera() 方法成功打开摄像头过程,用户 App 就可以实现拍照、连续拍照或录像的操作了。

    先看如何获取 ICameraService 服务,CameraManagerGlobal 类是 CameraManager 的子类、内容如下:

    /**
         * 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 {
    
            private static final String TAG = "CameraManagerGlobal";
            private final boolean DEBUG = false;
    
            private final int CAMERA_SERVICE_RECONNECT_DELAY_MS = 1000;
    
            // Singleton instance
            private static final CameraManagerGlobal gCameraManager =
                new CameraManagerGlobal();
    
            /**
             * This must match the ICameraService definition 服务名称 "media.camera"
             */
            private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
    
            // Camera ID -> Status map
            private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();
    
            // Registered availablility callbacks and their handlers
            private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
                new ArrayMap<AvailabilityCallback, Handler>();
    
            // torch client binder to set the torch mode with.
            private Binder mTorchClientBinder = new Binder();
    
            // Camera ID -> Torch status map
            private final ArrayMap<String, Integer> mTorchStatus = new ArrayMap<String, Integer>();
    
            // Registered torch callbacks and their handlers
            private final ArrayMap<TorchCallback, Handler> mTorchCallbackMap =
                    new ArrayMap<TorchCallback, Handler>();
    
            private final Object mLock = new Object();
    
            // Access only through getCameraService to deal with binder death
            private ICameraService mCameraService;
    
            // Singleton, don't allow construction
            private CameraManagerGlobal() {
            }
    
            public static final boolean sCameraServiceDisabled =
                    SystemProperties.getBoolean("config.disable_cameraservice", false);
    
            //> get 静态方法内容
            public static CameraManagerGlobal get() {
                return gCameraManager;
            }
    
            @Override
            public IBinder asBinder() {
                return this;
            }
    
            /**
             * Return a best-effort ICameraService.
             *
             * 

    This will be null if the camera service is not currently available. If the camera * service has died since the last use of the camera service, will try to reconnect to the * service.

    */
    public ICameraService getCameraService() { synchronized(mLock) { connectCameraServiceLocked(); if (mCameraService == null && !sCameraServiceDisabled) { Log.e(TAG, "Camera service is unavailable"); } return mCameraService; } } /** * Connect to the camera service if it's available, and set up listeners. * If the service is already connected, do nothing. * *

    Sets mCameraService to a valid pointer or null if the connection does not succeed.

    */
    private void connectCameraServiceLocked() { // Only reconnect if necessary if (mCameraService != null || sCameraServiceDisabled) return; Log.i(TAG, "Connecting to camera service"); //> 获取 "media.camera" 名称的服务 IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME); if (cameraServiceBinder == null) { // Camera service is now down, leave mCameraService as null return; } try { cameraServiceBinder.linkToDeath(this, /*flags*/ 0); } catch (RemoteException e) { // Camera service is now down, leave mCameraService as null return; } //> 通过 ICameraService.Stub.asInterface() 把 cameraServiceBinder 转化为 ICameraService 代理 ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder); try { CameraMetadataNative.setupGlobalVendorTagDescriptor(); } catch (ServiceSpecificException e) { handleRecoverableSetupErrors(e); } try { CameraStatus[] cameraStatuses = cameraService.addListener(this); for (CameraStatus c : cameraStatuses) { onStatusChangedLocked(c.status, c.cameraId); } //> 把 cameraService 保存起来 mCameraService = cameraService; } catch(ServiceSpecificException e) { // Unexpected failure throw new IllegalStateException("Failed to register a camera service listener", e); } catch (RemoteException e) { // Camera service is now down, leave mCameraService as null } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124

    源码 ICameraService.Stub.asInterface() 做了什么转化,代码如下:
    源码路径:@out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/dotdot/av/camera/aidl/android/hardware/ICameraService.java

    文件 ICameraService.java 是由 @frameworks/av/camera/aidl/android/hardware/ICameraService.aidl 文件内容编译系统自动生成的内容、如下:

    public interface ICameraService extends android.os.IInterface
    {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements android.hardware.ICameraService
    {
        private static final java.lang.String DESCRIPTOR = "android.hardware.ICameraService";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
    
        private static class Proxy implements android.hardware.ICameraService
        {
            private android.os.IBinder mRemote;
            Proxy(android.os.IBinder remote)
            {
                mRemote = remote;
            }
            @Override public android.os.IBinder asBinder()
            {
                return mRemote;
            }
        }
        /**
         * Cast an IBinder object into an android.hardware.ICameraService interface,
         * generating a proxy if needed.
         */
        public static android.hardware.ICameraService asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof android.hardware.ICameraService))) {
                return ((android.hardware.ICameraService)iin);
            }
            return new android.hardware.ICameraService.Stub.Proxy(obj);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    通过 Stub.asInterface() 就生成 ICameraService 代理服务,
    接下来 ICameraDeviceUser cameraUser = cameraService.connectDevice(callbacks, cameraId, mContext.getOpPackageName(), uid);把 android.os.Parcel 内容给了谁呢?
    连接谁呢? 内容如下:

    /**
         * Open a camera device through the new camera API
         * Only supported for device HAL versions >= 3.2
         */
    @Override public android.hardware.camera2.ICameraDeviceUser connectDevice(android.hardware.camera2.ICameraDeviceCallbacks callbacks, java.lang.String cameraId, java.lang.String opPackageName, int clientUid) throws android.os.RemoteException
    {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        android.hardware.camera2.ICameraDeviceUser _result;
        try {
            _data.writeInterfaceToken(DESCRIPTOR);
            _data.writeStrongBinder((((callbacks!=null))?(callbacks.asBinder()):(null)));
            _data.writeString(cameraId);
            _data.writeString(opPackageName);
            _data.writeInt(clientUid);
            mRemote.transact(Stub.TRANSACTION_connectDevice, _data, _reply, 0);
            _reply.readException();
            _result = android.hardware.camera2.ICameraDeviceUser.Stub.asInterface(_reply.readStrongBinder());
        }
        finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    网上很多关于 Camera 框架的描述博客、都没有描述这个过程,就直接跳转到 CameraService 侧的 CameraService::connectDevice() 代码上,
    分析 CameraService::connectDevice 是如何创建 CameraClient 的过程。

    我们一起梳理这块内容:

    分析如下:

     //> 获取 "media.camera" 名称的服务, cameraServiceBinder 对象持有 BnInterface
     IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
    
     //> 通过 ICameraService.Stub.asInterface() 把 cameraServiceBinder 转化为 ICameraService 代理
     ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代理就是 ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME) 获取到的服务,就是 “media.camera” 服务;ICameraServer 所持有的 mRemote 是 ICameraService 对象,通过 Stub.TRANSACTION_connectDevice 命令、使用transact方法发送给
    CameraService 的服务端、服务端解码后、调用 CameraService::connectDevice() 代码来处理;代码如下:
    代码路径:@@out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_arm64_armv8-a_cortex-a53_shared_core/
    gen/aidl/android/hardware/ICameraService.cpp

    ::android::status_t BnCameraService::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) 
    {
        ::android::status_t _aidl_ret_status = ::android::OK;
        switch (_aidl_code) {
            case Call::CONNECTDEVICE:
            {
                ::android::sp<::android::hardware::camera2::ICameraDeviceCallbacks> in_callbacks;
                ::android::String16 in_cameraId;
                ::android::String16 in_opPackageName;
                int32_t in_clientUid;
                ::android::sp<::android::hardware::camera2::ICameraDeviceUser> _aidl_return;
                if (!(_aidl_data.checkInterface(this))) {
                _aidl_ret_status = ::android::BAD_TYPE;
                break;
                }
                _aidl_ret_status = _aidl_data.readStrongBinder(&in_callbacks);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                _aidl_ret_status = _aidl_data.readString16(&in_cameraId);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                _aidl_ret_status = _aidl_data.readString16(&in_opPackageName);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                _aidl_ret_status = _aidl_data.readInt32(&in_clientUid);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                //> 此处调用 connectDevice(in_callbacks, in_cameraId, in_opPackageName, in_clientUid, &_aidl_return)
                ::android::binder::Status _aidl_status(connectDevice(in_callbacks, in_cameraId, in_opPackageName, in_clientUid, &_aidl_return));
                _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                if (!_aidl_status.isOk()) {
                break;
                }
                _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::hardware::camera2::ICameraDeviceUser::asBinder(_aidl_return));
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
            }
            break;
            case Call::CONNECTLEGACY:
            {
                ::android::sp<::android::hardware::ICameraClient> in_client;
                int32_t in_cameraId;
                int32_t in_halVersion;
                ::android::String16 in_opPackageName;
                int32_t in_clientUid;
                ::android::sp<::android::hardware::ICamera> _aidl_return;
                if (!(_aidl_data.checkInterface(this))) {
                _aidl_ret_status = ::android::BAD_TYPE;
                break;
                }
                _aidl_ret_status = _aidl_data.readStrongBinder(&in_client);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                _aidl_ret_status = _aidl_data.readInt32(&in_cameraId);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                _aidl_ret_status = _aidl_data.readInt32(&in_halVersion);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                _aidl_ret_status = _aidl_data.readString16(&in_opPackageName);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                _aidl_ret_status = _aidl_data.readInt32(&in_clientUid);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                ::android::binder::Status _aidl_status(connectLegacy(in_client, in_cameraId, in_halVersion, in_opPackageName, in_clientUid, &_aidl_return));
                _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
                if (!_aidl_status.isOk()) {
                break;
                }
                _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::hardware::ICamera::asBinder(_aidl_return));
                if (((_aidl_ret_status) != (::android::OK))) {
                break;
                }
            }
            break;
            default:
                {
                    _aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
                }
            break;
        }
        if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
            _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
        }
        return _aidl_ret_status;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    那接下来看看 CameraService 服务端的 connectDevice() 代码,内容如下:
    源码路径:@frameworks/av/services/camera/libcameraservcie/CameraService.cpp 中 connectDevice 方法内容如下:

    Status CameraService::connectDevice(
            const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
            const String16& cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp<hardware::camera2::ICameraDeviceUser>* device) {
    
        ATRACE_CALL();
        Status ret = Status::ok();
        String8 id = String8(cameraId);
        sp<CameraDeviceClient> client = nullptr;
        ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
                CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
                clientUid, USE_CALLING_PID, API_2,
                /*legacyMode*/ false, /*shimUpdateOnly*/ false,
                /*out*/client);
    
        if(!ret.isOk()) {
            logRejected(id, getCallingPid(), String8(clientPackageName),
                    ret.toString8());
            return ret;
        }
    
        *device = client;
        return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    该方法中调用 connectHelper() 来连接摄像头,代码如下:

    template<class CALLBACK, class CLIENT>
    Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
            int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
            apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
            /*out*/sp<CLIENT>& device) {
        binder::Status ret = binder::Status::ok();
    
        String8 clientName8(clientPackageName);
    
        int originalClientPid = 0;
    
        ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
                "Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
                (halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
                static_cast<int>(effectiveApiLevel));
    
        sp<CLIENT> client = nullptr;
        {
            // Acquire mServiceLock and prevent other clients from connecting
            std::unique_ptr<AutoConditionLock> lock =
                    AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
    
            if (lock == nullptr) {
                ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
                        , clientPid);
                return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                        "Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
                        cameraId.string(), clientName8.string(), clientPid);
            }
    
            // Enforce client permissions and do basic sanity checks
            if(!(ret = validateConnectLocked(cameraId, clientName8,
                    /*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
                return ret;
            }
    
            // Check the shim parameters after acquiring lock, if they have already been updated and
            // we were doing a shim update, return immediately
            if (shimUpdateOnly) {
                auto cameraState = getCameraState(cameraId);
                if (cameraState != nullptr) {
                    if (!cameraState->getShimParams().isEmpty()) return ret;
                }
            }
    
            status_t err;
    
            sp<BasicClient> clientTmp = nullptr;
            std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
    
            if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
                    IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
                    /*out*/&partial)) != NO_ERROR) {
                switch (err) {
                    case -ENODEV:
                        return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
                                "No camera device with ID \"%s\" currently available",
                                cameraId.string());
                    case -EBUSY:
                        return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                                "Higher-priority client using camera, ID \"%s\" currently unavailable",
                                cameraId.string());
                    default:
                        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                                "Unexpected error %s (%d) opening camera \"%s\"",
                                strerror(-err), err, cameraId.string());
                }
            }
    
            if (clientTmp.get() != nullptr) {
                // Handle special case for API1 MediaRecorder where the existing client is returned
                device = static_cast<CLIENT*>(clientTmp.get());
                return ret;
            }
    
            // give flashlight a chance to close devices if necessary.
            mFlashlight->prepareDeviceOpen(cameraId);
    
            int facing = -1;
            int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);
            if (facing == -1) {
                ALOGE("%s: Unable to get camera device \"%s\"  facing", __FUNCTION__, cameraId.string());
                return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                        "Unable to get camera device \"%s\" facing", cameraId.string());
            }
    
            //> 1. 创建 CameraClient
            sp<BasicClient> tmp = nullptr;
            if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
                    clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
                    /*out*/&tmp)).isOk()) {
                return ret;
            }
            client = static_cast<CLIENT*>(tmp.get());
    
            LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
                    __FUNCTION__);
    
            //> 2. 初始化 client
            err = client->initialize(mCameraProviderManager);
    
            if (err != OK) {
                ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
                // Errors could be from the HAL module open call or from AppOpsManager
                switch(err) {
                    case BAD_VALUE:
                        return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                                "Illegal argument to HAL module for camera \"%s\"", cameraId.string());
                    case -EBUSY:
                        return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                                "Camera \"%s\" is already open", cameraId.string());
                    case -EUSERS:
                        return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                                "Too many cameras already open, cannot open camera \"%s\"",
                                cameraId.string());
                    case PERMISSION_DENIED:
                        return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                                "No permission to open camera \"%s\"", cameraId.string());
                    case -EACCES:
                        return STATUS_ERROR_FMT(ERROR_DISABLED,
                                "Camera \"%s\" disabled by policy", cameraId.string());
                    case -ENODEV:
                    default:
                        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                                "Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
                                strerror(-err), err);
                }
            }
    
            // Update shim paremeters for legacy clients
            if (effectiveApiLevel == API_1) {
                // Assume we have always received a Client subclass for API1
                sp<Client> shimClient = reinterpret_cast<Client*>(client.get());
                String8 rawParams = shimClient->getParameters();
                CameraParameters params(rawParams);
    
                auto cameraState = getCameraState(cameraId);
                if (cameraState != nullptr) {
                    cameraState->setShimParams(params);
                } else {
                    ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",
                            __FUNCTION__, cameraId.string());
                }
            }
    
            if (shimUpdateOnly) {
                // If only updating legacy shim parameters, immediately disconnect client
                mServiceLock.unlock();
                client->disconnect();
                mServiceLock.lock();
            } else {
                // Otherwise, add client to active clients list
                finishConnectLocked(client, partial);
            }
        } // lock is destroyed, allow further connect calls
    
        // Important: release the mutex here so the client can call back into the service from its
        // destructor (can be at the end of the call)
        device = client;
        return ret;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161

    代码调用 makeClient() 和 client->initialize() 函数,打开相机就完成了。
    我们先看 makeClient() 创建不同 hal 版本的 BasicClient 的相机。

    Status CameraService::makeClient(const sp<CameraService>& cameraService,
            const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
            int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
            int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
            /*out*/sp<BasicClient>* client) {
    
        if (halVersion < 0 || halVersion == deviceVersion) {
            // Default path: HAL version is unspecified by caller, create CameraClient
            // based on device version reported by the HAL.
            switch(deviceVersion) {
              case CAMERA_DEVICE_API_VERSION_1_0:
                if (effectiveApiLevel == API_1) {  // Camera1 API route
                    sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                    *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                            facing, clientPid, clientUid, getpid(), legacyMode);
                } else { // Camera2 API route
                    ALOGW("Camera using old HAL version: %d", deviceVersion);
                    return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
                            "Camera device \"%s\" HAL version %d does not support camera2 API",
                            cameraId.string(), deviceVersion);
                }
                break;
              case CAMERA_DEVICE_API_VERSION_3_0:
              case CAMERA_DEVICE_API_VERSION_3_1:
              case CAMERA_DEVICE_API_VERSION_3_2:
              case CAMERA_DEVICE_API_VERSION_3_3:
              case CAMERA_DEVICE_API_VERSION_3_4:
                if (effectiveApiLevel == API_1) { // Camera1 API route
                    sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                    *client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                            facing, clientPid, clientUid, servicePid, legacyMode);
                } else { // Camera2 API route
                    sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                            static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
                    *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
                            facing, clientPid, clientUid, servicePid);
                }
                break;
              default:
                // Should not be reachable
                ALOGE("Unknown camera device HAL version: %d", deviceVersion);
                return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                        "Camera device \"%s\" has unknown HAL version %d",
                        cameraId.string(), deviceVersion);
            }
        } else {
            // A particular HAL version is requested by caller. Create CameraClient
            // based on the requested HAL version.
            if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
                halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
                // Only support higher HAL version device opened as HAL1.0 device.
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                        facing, clientPid, clientUid, servicePid, legacyMode);
            } else {
                // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
                ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
                        " opened as HAL %x device", halVersion, deviceVersion,
                        CAMERA_DEVICE_API_VERSION_1_0);
                return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                        "Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
                        cameraId.string(), deviceVersion, halVersion);
            }
        }
        return Status::ok();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    代码中创建 client 有 CameraClient()、Camera2Client() 和 CameraDeviceClient() 方法,根据相机 HAL 中的 deviceVersion 描述的内容,分别对应起来;
    我关注的 CameraDeviceClient() 是 API_2 的方法, 因笔者虚拟摄像头就使用api V2 .
    源码路径: @frameworks/av/services/camera/libcameraservcie/api2/CameraDeviceClient.h

    class CameraDeviceClient :
            public Camera2ClientBase<CameraDeviceClientBase>,
            public camera2::FrameProcessorBase::FilteredListener
    {
    public:
        /**
         * ICameraDeviceUser interface (see ICameraDeviceUser for details)
         */
    
        // Note that the callee gets a copy of the metadata.
        virtual binder::Status submitRequest(
                const hardware::camera2::CaptureRequest& request,
                bool streaming = false,
                /*out*/
                hardware::camera2::utils::SubmitInfo *submitInfo = nullptr) override;
    
        virtual binder::Status createStream(
                const hardware::camera2::params::OutputConfiguration &outputConfiguration,
                /*out*/
                int32_t* newStreamId = NULL) override;
        
        // Create an input stream of width, height, and format.
        virtual binder::Status createInputStream(int width, int height, int format,
                /*out*/
                int32_t* newStreamId = NULL) override;
        /**
         * Interface used by CameraService
         */
    
        CameraDeviceClient(const sp<CameraService>& cameraService,
                const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
                const String16& clientPackageName,
                const String8& cameraId,
                int cameraFacing,
                int clientPid,
                uid_t clientUid,
                int servicePid);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    源码路径: @frameworks/av/services/camera/libcameraservcie/api2/CameraDeviceClient.cpp

    // Interface used by CameraService
    //> 构造函数
    CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
            const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
            const String16& clientPackageName,
            const String8& cameraId,
            int cameraFacing,
            int clientPid,
            uid_t clientUid,
            int servicePid) :
        Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                    cameraId, cameraFacing, clientPid, clientUid, servicePid),
        mInputStream(),
        mStreamingRequestId(REQUEST_ID_NONE),
        mRequestIdCounter(0) {
    
        ATRACE_CALL();
        ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
    }
    //> 初始化函数
    status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager) {
        return initializeImpl(manager);
    }
    
    template<typename TProviderPtr>
    status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr) {
        ATRACE_CALL();
        status_t res;
    
        res = Camera2ClientBase::initialize(providerPtr);
        if (res != OK) {
            return res;
        }
    
        String8 threadName;
        mFrameProcessor = new FrameProcessorBase(mDevice);
        threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
        mFrameProcessor->run(threadName.string());
    
        mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                          FRAME_PROCESSOR_LISTENER_MAX_ID,
                                          /*listener*/this,
                                          /*sendPartials*/true);
    
        return OK;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    构造函数和初始化函数都调用 Camera2ClientBase 类的方法.源码如下:
    源码路径:@frameworks/av/services/libcameraservcie/common/Camera2ClientBase.cpp

    // Interface used by CameraService
    //> 构造方法
    template <typename TClientBase>
    Camera2ClientBase<TClientBase>::Camera2ClientBase(
            const sp<CameraService>& cameraService,
            const sp<TCamCallbacks>& remoteCallback,
            const String16& clientPackageName,
            const String8& cameraId,
            int cameraFacing,
            int clientPid,
            uid_t clientUid,
            int servicePid):
            TClientBase(cameraService, remoteCallback, clientPackageName,
                    cameraId, cameraFacing, clientPid, clientUid, servicePid),
            mSharedCameraCallbacks(remoteCallback),
            mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
            mDeviceActive(false)
    {
        ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
                String8(clientPackageName).string(), clientPid, clientUid);
    
        mInitialClientPid = clientPid;
        mDevice = new Camera3Device(cameraId);
        LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
    }
    
    //> 初始化函数
    template <typename TClientBase>
    template <typename TProviderPtr>
    status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr) {
        ATRACE_CALL();
        ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
              TClientBase::mCameraIdStr.string());
        status_t res;
    
        // Verify ops permissions
        res = TClientBase::startCameraOps();
        if (res != OK) {
            return res;
        }
    
        if (mDevice == NULL) {
            ALOGE("%s: Camera %s: No device connected",
                    __FUNCTION__, TClientBase::mCameraIdStr.string());
            return NO_INIT;
        }
    
        res = mDevice->initialize(providerPtr);
        if (res != OK) {
            ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
                    __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
            return res;
        }
    
        wp<CameraDeviceBase::NotificationListener> weakThis(this);
        res = mDevice->setNotifyCallback(weakThis);
    
        return OK;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    构造方法中 new Camera3Device(cameraId) 相机,
    源码路径:@frameworks/av/services/camera/libcameraservcie/device3/Camera3Device.cpp

    //> 构造函数
    Camera3Device::Camera3Device(const String8 &id):
            mId(id),
            mOperatingMode(NO_MODE),
            mIsConstrainedHighSpeedConfiguration(false),
            mStatus(STATUS_UNINITIALIZED),
            mStatusWaiters(0),
            mUsePartialResult(false),
            mNumPartialResults(1),
            mTimestampOffset(0),
            mNextResultFrameNumber(0),
            mNextReprocessResultFrameNumber(0),
            mNextShutterFrameNumber(0),
            mNextReprocessShutterFrameNumber(0),
            mListener(NULL),
            mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
    {
        ATRACE_CALL();
        camera3_callback_ops::notify = &sNotify;
        camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
        ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
    }
    //> 初始化函数
    status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
        ATRACE_CALL();
        Mutex::Autolock il(mInterfaceLock);
        Mutex::Autolock l(mLock);
    
        ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
        if (mStatus != STATUS_UNINITIALIZED) {
            CLOGE("Already initialized!");
            return INVALID_OPERATION;
        }
        if (manager == nullptr) return INVALID_OPERATION;
    
        sp<ICameraDeviceSession> session;
        ATRACE_BEGIN("CameraHal::openSession");
        status_t res = manager->openSession(mId.string(), this,
                /*out*/ &session);
        ATRACE_END();
        if (res != OK) {
            SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
            return res;
        }
    
        res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
        if (res != OK) {
            SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
            session->close();
            return res;
        }
    
        std::shared_ptr<RequestMetadataQueue> queue;
        auto requestQueueRet = session->getCaptureRequestMetadataQueue(
            [&queue](const auto& descriptor) {
                queue = std::make_shared<RequestMetadataQueue>(descriptor);
                if (!queue->isValid() || queue->availableToWrite() <= 0) {
                    ALOGE("HAL returns empty request metadata fmq, not use it");
                    queue = nullptr;
                    // don't use the queue onwards.
                }
            });
        if (!requestQueueRet.isOk()) {
            ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
                    requestQueueRet.description().c_str());
            return DEAD_OBJECT;
        }
    
        std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
        auto resultQueueRet = session->getCaptureResultMetadataQueue(
            [&resQueue](const auto& descriptor) {
                resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
                if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
                    ALOGE("HAL returns empty result metadata fmq, not use it");
                    resQueue = nullptr;
                    // Don't use the resQueue onwards.
                }
            });
        if (!resultQueueRet.isOk()) {
            ALOGE("Transaction error when getting result metadata queue from camera session: %s",
                    resultQueueRet.description().c_str());
            return DEAD_OBJECT;
        }
        IF_ALOGV() {
            session->interfaceChain([](
                ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                    ALOGV("Session interface chain:");
                    for (auto iface : interfaceChain) {
                        ALOGV("  %s", iface.c_str());
                    }
                });
        }
    
        mInterface = new HalInterface(session, queue);
        std::string providerType;
        mVendorTagId = manager->getProviderTagIdLocked(mId.string());
    
        return initializeCommonLocked();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    由上面的构建函数和初始化函数、我们看到 ICameraDeviceSession、mResultMetadataQueue 等新特征变量内容,在看看 initializeCommonLocked() 函数内容如下:

    status_t Camera3Device::initializeCommonLocked() {
    
        /** Start up status tracker thread */
        mStatusTracker = new StatusTracker(this);
        status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
        if (res != OK) {
            SET_ERR_L("Unable to start status tracking thread: %s (%d)",
                    strerror(-res), res);
            mInterface->close();
            mStatusTracker.clear();
            return res;
        }
    
        /** Register in-flight map to the status tracker */
        mInFlightStatusId = mStatusTracker->addComponent();
    
        /** Create buffer manager */
        mBufferManager = new Camera3BufferManager();
    
        mTagMonitor.initialize(mVendorTagId);
    
        /** Start up request queue thread */
        mRequestThread = new RequestThread(this, mStatusTracker, mInterface);
        res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
        if (res != OK) {
            SET_ERR_L("Unable to start request queue thread: %s (%d)",
                    strerror(-res), res);
            mInterface->close();
            mRequestThread.clear();
            return res;
        }
    
        mPreparerThread = new PreparerThread();
    
        internalUpdateStatusLocked(STATUS_UNCONFIGURED);
        mNextStreamId = 0;
        mDummyStreamId = NO_STREAM;
        mNeedConfig = true;
        mPauseStateNotify = false;
    
        // Measure the clock domain offset between camera and video/hw_composer
        camera_metadata_entry timestampSource =
                mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
        if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
                ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
            mTimestampOffset = getMonoToBoottimeOffset();
        }
    
        // Will the HAL be sending in early partial result metadata?
        camera_metadata_entry partialResultsCount =
                mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
        if (partialResultsCount.count > 0) {
            mNumPartialResults = partialResultsCount.data.i32[0];
            mUsePartialResult = (mNumPartialResults > 1);
        }
    
        camera_metadata_entry configs =
                mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
        for (uint32_t i = 0; i < configs.count; i += 4) {
            if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
                    configs.data.i32[i + 3] ==
                    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
                mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
                        configs.data.i32[i + 2]));
            }
        }
    
        return OK;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    HAL 3 相机子系统将多个运行模式整合为一个统一的视图,您可以使用这种视图实现之前的任何模式以及一些其他模式,例如连拍模式。这样一来,便可以提高用户对聚焦、曝光以及更多后期处理(例如降噪、对比度和锐化)效果的控制能力。此外,这种简化的视图还能够使应用开发者更轻松地使用相机的各种功能。

  • 相关阅读:
    uni app 打肉肉(打飞机)小游戏
    Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单
    pytorch 使用DataParallel 单机多卡和单卡保存和加载模型的正确方法
    Linux shell编程学习笔记20:case ... esac、continue 和break语句
    NR 物理层卷积码 slide 9
    unity 限制 相机移动 区域(无需碰撞检测)
    解决zsh远程启动后台进程后无法退出的问题
    uniapp如何根据不同角色自定义不同的tabbar
    Kerberos 身份验证
    node.js+npm安装(win11适用)
  • 原文地址:https://blog.csdn.net/weixin_38387929/article/details/126303930