Android 8.0系统源码分析--openCamera启动过程源码分析

本文深入探讨Android 8.0系统中相机的openCamera过程,从应用层到框架层,分析CameraManager如何打开相机,涉及线程同步、Binder通信以及CameraService在native层的角色。通过详细源码解析,阐述相机预览的核心——buffer轮转,并预告后续将讨论openCamera的剩余逻辑。
摘要由CSDN通过智能技术生成

     今年一进公司就开始搞相机开发,一直是在搞相机应用层,不过自己的学习心一直没停,闲暇之余就研究一下相机的framework、HAL层的东西,平时工作中碰到的和自己接触到的,相机中最复杂的就是预览了,有了一些体会也不想放下,所以决定写一系列关于Android相机的博客,把自己学习到的东西记录下来。

     说起Android相机的东西,从应用层的角度来看,基本就是四个重要的节点了:openCamera、createCaptureSession、preview、capture,最复杂的就是preview了,要理解preview,那么就要求大家对Android的View显示系统有一定的理解,才能更好的理解相机的预览。相机的预览其实就是使用预览区的SurfaceView对应的surface创建一条预览流,然后framework从预览surface当中获取到显示buffer,这里用于显示的buffer会根据数量来获取,华为手机的相机framework+HAL两部分一般总共需要7个buffer,每个buffer都对应预览区的一屏的大小,它就是HAL、算法各层填充完毕后,要交给SurfaceFlinger用于显示的预览区大小的所有像素点的byte数组,这7个buffer每次在CameraServer进程获取一个,然后通过HIDL下发给CameraDaemon进程,交给算法、HAL层进行着色渲染,完成后再通过CameraServer进程交给SurfaceFlinger,最后显示在屏幕上,这样不断的轮转,我们就看到了预览区会不断的变动,这里的buffer轮转也就是相机最核心的部分了。我们后期的博客具体在讲关于buffer轮转的知识。

     这节我们先来说说从应用层调用openCamera之后的执行逻辑。openCamera的方法实现是在frameworks\base\core\java\android\hardware\camera2\CameraManager.java类中完成的,CameraManager和我们应用中经常使用的WindowManager、PackageManager一样,都可以通过context上下文获取到,它也是在frameworks\base\core\java\android\app\SystemServiceRegistry.java类中通过Context.CAMERA_SERVICE键值注册的,源码如下:


     我们拿到CameraManager类的对象之后,就可以调用它的openCamera方法来打开相机了,CameraManager类的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);
    }
     这个方法的实现很简单,就是调用openCameraForUid来进一步处理,我们先来看看调用该方法需要传递的参数,第一个表示要打开的目标Camera的id,华为手机上该值一般有两个:0和1,0表示后摄,当然也是主摄,1表示前摄,我们怎么知道该值的取值呢?可以通过调用CameraManager类的getCameraIdList()方法来获取,该方法会将当前已经注册成功的camera硬件对应的id列表返回给我们应用层,硬件注册都是驱动层的东西了,那一步离我们现在的阶段还很远。我们再来看一下第二个参数CameraDevice.StateCallback ,它是定义在 frameworks\base\core\java\android\hardware\camera2\CameraDevice.java类中的一个内部类,StateCallback类的定义源码如下:

    public static abstract class StateCallback {
       /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device is in use already.
         *
         * <p>
         * This error can be produced when opening the camera fails due to the camera
        *  being used by a higher-priority camera API client.
         * </p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_IN_USE = 1;

        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device could not be opened
         * because there are too many other open camera devices.
         *
         * <p>
         * The system-wide limit for number of open cameras has been reached,
         * and more camera devices cannot be opened until previous instances are
         * closed.
         * </p>
         *
         * <p>
         * This error can be produced when opening the camera fails.
         * </p>
         *
         * @see #onError
         */
        public static final int ERROR_MAX_CAMERAS_IN_USE = 2;

        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device could not be opened due to a device
         * policy.
         *
         * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
         * @see #onError
         */
        public static final int ERROR_CAMERA_DISABLED = 3;

       /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device has encountered a fatal error.
         *
         * <p>The camera device needs to be re-opened to be used again.</p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_DEVICE = 4;

        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera service has encountered a fatal error.
         *
         * <p>The Android device may need to be shut down and restarted to restore
         * camera function, or there may be a persistent hardware problem.</p>
         *
         * <p>An attempt at recovery <i>may</i> be possible by closing the
         * CameraDevice and the CameraManager, and trying to acquire all resources
         * again from scratch.</p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_SERVICE = 5;

        /** @hide */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(prefix = {"ERROR_"}, value =
            {ERROR_CAMERA_IN_USE,
             ERROR_MAX_CAMERAS_IN_USE,
             ERROR_CAMERA_DISABLED,
             ERROR_CAMERA_DEVICE,
             ERROR_CAMERA_SERVICE })
        public @interface ErrorCode {};

        /**
         * The method called when a camera device has finished opening.
         *
         * <p>At this point, the camera device is ready to use, and
         * {@link CameraDevice#createCaptureSession} can be called to set up the first capture
         * session.</p>
         *
         * @param camera the camera device that has become opened
         */
        public abstract void onOpened(@NonNull CameraDevice camera); // Must implement

        /**
         * The method called when a camera device has been closed with
         * {@link CameraDevice#close}.
         *
         * <p>Any attempt to call methods on this CameraDevice in the
         * future will throw a {@link IllegalStateException}.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the camera device that has become closed
         */
        public void onClosed(@NonNull CameraDevice camera) {
            // Default empty implementation
        }

        /**
         * The method called when a camera device is no longer available for
         * use.
         *
         * <p>This callback may be called instead of {@link #onOpened}
         * if opening the camera fails.</p>
         *
         * <p>Any attempt to call methods on this CameraDevice will throw a
         * {@link CameraAccessException}. The disconnection could be due to a
         * change in security policy or permissions; the physical disconnection
         * of a removable camera device; or the camera being needed for a
         * higher-priority camera API client.</p>
         *
         * <p>There may still be capture callbacks that are invoked
         * after this method is called, or new image buffers that are delivered
         * to active outputs.</p>
         *
         * <p>The default implementation logs a notice to the system log
         * about the disconnection.</p>
         *
         * <p>You should clean up the camera with {@link CameraDevice#close} after
         * this happens, as it is not recoverable until the camera can be opened
         * again. For most use cases, this will be when the camera again becomes
         * {@link CameraManager.AvailabilityCallback#onCameraAvailable available}.
         * </p>
         *
         * @param camera the device that has been disconnected
         */
        public abstract void onDisconnected(@NonNull CameraDevice camera); // Must implement

        /**
         * The method called when a camera device has encountered a serious error.
         *
         * <p>This callback may be called instead of {@link #onOpened}
         * if opening the camera fails.</p>
         *
         * <p>This indicates a failure of the camera device or camera service in
         * some way. Any attempt to call methods on this CameraDevice in the
         * future will throw a {@link CameraAccessException} with the
         * {@link CameraAccessException#CAMERA_ERROR CAMERA_ERROR} reason.
         * </p>
         *
         * <p>There may still be capture completion or camera stream callbacks
         * that will be called after this error is received.</p>
         *
         * <p>You should clean up the camera with {@link CameraDevice#close} after
         * this happens. Further attempts at recovery are error-code specific.</p>
         *
         * @param camera The device reporting the error
         * @param error The error code.
         *
         * @see #ERROR_CAMERA_IN_USE
         * @see #ERROR_MAX_CAMERAS_IN_USE
         * @see #ERROR_CAMERA_DISABLED
         * @see #ERROR_CAMERA_DEVICE
         * @see #ERROR_CAMERA_SERVICE
         */
        public abstract void onError(@NonNull CameraDevice camera,
                @ErrorCode int error); // Must implement
    }
我们从这个类所定义的方法就能够非常清楚的看到,它这几个回调的意图了:onOpened就是成功打开camera之后的回调,而且它会返回一个CameraDevice camera对象给我们应用层,基本上操作相机所有重要的工作都是由它来中转实现的,所以应用层拿到这个对象之后,就可以使用它作很多其他的工作了,在接下来的分析过程中,我们也会看到,这个对象在framework中是怎么构建好,然后又是怎么回传给我们应用层的;onClosed方法就是当相机关闭时的回调了;onDisconnected方法就是相机断开连接时的回调;onError方法就是相机出错时的回调了。

我们再来看看最后一个参数Handler handler,为什么要传一个Handler进来呢?它的目的就是为了保证线程不切换,假如我们在应用层在工作线程B中执行openCamera的方法,同时将线程B对应的Handler对象传进来,那么打开成功之后,framework为了保证线程同步,也会使用该handler对象,将消息发送到线程B的Looper循环上,这就是传入一个Handler对象的原因了,我们在后面的分析过程中会看到它的使用。

好,参数分析完了,我们继续来看一下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 Illega
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红-旺永福

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值