• <Android Framework 之路>Android5.1 Camera Framework(一)


    Android5.0 Camera Framework 简介

    CameraService启动

    CameraService是在MediaServer启动过程中进行的
    main_mediaserver.cpp (frameworksavmediamediaserver)

    ......
    AudioFlinger::instantiate(); //audioflinger服务,音频相关
    MediaPlayerService::instantiate(); //mediaplayerservice,媒体播放相关
    CameraService::instantiate();//CameraService
    AudioPolicyService::instantiate(); //音频相关
    ......

    在 main函数中会执行到CameraService::instantiate(), CameraService 本身并没有实现这个方法
    CameraService.cpp (frameworksavservicescameralibcameraservice)
    CameraService.h (frameworksavservicescameralibcameraservice)
    BinderService.h (frameworks ativeincludeinder)

    class CameraService :
        public BinderService<CameraService>,
        public BnCameraService,
        public IBinder::DeathRecipient,
        public camera_module_callbacks_t
    {
        ......
    }

    在其父类中寻找instantiate()函数,BinderService是一个模板类

    template<typename SERVICE>
    class BinderService
    {
    public:
        static status_t publish(bool allowIsolated = false) { //BinderService::publish
            sp<IServiceManager> sm(defaultServiceManager()); //拿到ServiceManager的Bp
            return sm->addService(
                    String16(SERVICE::getServiceName()),
                    new SERVICE(), allowIsolated);           //这里的SERVICE就是CameraService
        }
        .....
        static void instantiate() { publish(); }      //BinderService::instantiate
        .....
    };

    这里会new CameraService(),

    CameraService::CameraService()
        :mSoundRef(0), mModule(0)
    {
        ALOGI("CameraService started (pid=%d)", getpid());
        gCameraService = this;    //保存一个本地指针
        for (size_t i = 0; i < MAX_CAMERAS; ++i) {
            mStatusList[i] = ICameraServiceListener::STATUS_PRESENT;
        }
        this->camera_device_status_change = android::camera_device_status_change;
    }

    到这里,CameraService就启动了。

    Camera连接过程

    Camera.java (frameworksasecorejavaandroidhardware)
    Camera.cpp (frameworksavcamera)
    android_hardware_Camera.cpp (frameworksasecorejni)
    从java->jni->CPP的典型过程
    首先从Camera.java入手,这里通过open()方法,创建Camera

        public static Camera open(int cameraId) {
            return new Camera(cameraId);
        }
    
        public static Camera open() {
            int numberOfCameras = getNumberOfCameras();
            CameraInfo cameraInfo = new CameraInfo();
            for (int i = 0; i < numberOfCameras; i++) {
                getCameraInfo(i, cameraInfo);
                if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                    return new Camera(i);
                }
            }
            return null;
        }

    两个open()方法,默认打开后置摄像头,new Camera()对象,

        Camera(int cameraId) {
            int err = cameraInitNormal(cameraId);//做事的主要地方
            if (checkInitErrors(err)) {
                switch(err) {                    //通过返回的错误信息,抛不同的异常信息
                    case EACCESS:
                        throw new RuntimeException("Fail to connect to camera service");
                    case ENODEV:
                        throw new RuntimeException("Camera initialization failed");
                    default:
                        // Should never hit this.
                        throw new RuntimeException("Unknown camera error");
                }
            }
        }

    接下来看下代码,最后会落脚到哪一块呢?

        private int cameraInitNormal(int cameraId) {
            //这里的CAMERA_HAL_API_VERSION_NORMAL_CONNECT后面会提到用来区别不同的connect
            return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
        }
        ......
        private int cameraInitVersion(int cameraId, int halVersion) {
            mShutterCallback = null;           
            mRawImageCallback = null;
            mJpegCallback = null;
            mPreviewCallback = null;
            mPostviewCallback = null;
            mUsingPreviewAllocation = false;
            mZoomListener = null;             //初始化几个callback和一些变量
    
            Looper looper;            //mEventHandler后面会讲到是对底层上报内容的处理handler
            if ((looper = Looper.myLooper()) != null) {
                mEventHandler = new EventHandler(this, looper);
            } else if ((looper = Looper.getMainLooper()) != null) {
                mEventHandler = new EventHandler(this, looper);
            } else {
                mEventHandler = null;
            }
    
            String packageName = ActivityThread.currentPackageName();
    
            return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
        }
    

    可以看到native_setup是一个native方法,具体实现在
    android_hardware_Camera.cpp (frameworksasecorejni)

    static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
        jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
    {
        ......
        sp<Camera> camera;
        //之前在创建Camera对象的时候设置的一个常量,此时走到connect方法
        if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
            // Default path: hal version is don't care, do normal camera connect.
            camera = Camera::connect(cameraId, clientName,
                    Camera::USE_CALLING_UID);
        } else {
            jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
                    Camera::USE_CALLING_UID, camera);
            if (status != NO_ERROR) {
                return status;
            }
        }
        ......
        // We use a weak reference so the Camera object can be garbage collected.
        // The reference is only used as a proxy for callbacks.
        sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
        context->incStrong((void*)android_hardware_Camera_native_setup);
        camera->setListener(context);//listener用于处理底层数据上报
    
        // save context in opaque field
        env->SetLongField(thiz, fields.context, (jlong)context.get());
        return NO_ERROR;
    }
    

    从JNI往下就是CPP,继续探寻Camera连接过程
    Camera.cpp (frameworksavcamera)
    CameraBase.cpp (frameworksavcamera)

    sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
            int clientUid)
    {   //CameraBaseT为模板类
        return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
    }

    CameraBase中connect函数模板替换成

    sp<Camera> CameraBase<Camera, CameraTraits<Camera>>::connect(int cameraId,
                                                   const String16& clientPackageName,
                                                   int clientUid)
    {
        ALOGV("%s: connect", __FUNCTION__);
        sp<Camera> c = new Camera(cameraId);
        sp<ICameraClient> cl = c;
        status_t status = NO_ERROR;
        const sp<ICameraService>& cs = getCameraService();//获取CameraService的Bp
    
        if (cs != 0) {
            //这里TCamConncectService是一个函数指针,指向的是ICameraService中的connect方法
            TCamConnectService fnConnectService = TCamTraits::fnConnectService;
            status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
                                                 /*out*/ c->mCamera);
            status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
                                                 /*out*/ c->mCamera);
        }
        if (status == OK && c->mCamera != 0) {
            c->mCamera->asBinder()->linkToDeath(c);
            c->mStatus = NO_ERROR;
        } else {
            ALOGW("An error occurred while connecting to camera: %d", cameraId);
            c.clear();
        }
        return c;
    }

    这里可能有点绕,稍微讲解一下,模板上
    template

    template <typename TCam>
    struct CameraTraits {
    };
    template <typename TCam, typename TCamTraits = CameraTraits<TCam> >

    然后我们再到Camera.h中看
    template <>
    struct CameraTraits
    {
    typedef CameraListener TCamListener;
    typedef ICamera TCamUser;
    typedef ICameraClient TCamCallbacks;
    typedef status_t (ICameraService::*TCamConnectService)(const sp&,
    int, const String16&, int,
    /out/
    sp&);
    static TCamConnectService fnConnectService;
    };
    中间有些过程,应该好理解了,这里绕了一下,最后落脚到ICameraService.cpp中的connect方法,这一部分涉及到Binder机制比较多,暂时先不讲解具体内容,注意调用的地方即可。
    ICameraService.cpp (frameworksavcamera)

        // connect to camera service (android.hardware.Camera)
        virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
                                 const String16 &clientPackageName, int clientUid,
                                 /*out*/
                                 sp<ICamera>& device)
        {
            Parcel data, reply;
            data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
            data.writeStrongBinder(cameraClient->asBinder());
            data.writeInt32(cameraId);
            data.writeString16(clientPackageName);
            data.writeInt32(clientUid);
            remote()->transact(BnCameraService::CONNECT, data, &reply);//通过binder远端调用传入的code为BnCameraservice::CONNECT
    
            if (readExceptionCode(reply)) return -EPROTO;
            status_t status = reply.readInt32();
            if (reply.readInt32() != 0) {
                device = interface_cast<ICamera>(reply.readStrongBinder());//转换为BpCamera
            }
            return status;
        }

    接下来或执行到BnCameraService的onTransact()方法,主要就是switch_case,上面传入的是CONNECT

    status_t BnCameraService::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        switch(code) {
        ......
            case CONNECT: {
                CHECK_INTERFACE(ICameraService, data, reply);
                sp<ICameraClient> cameraClient =
                        interface_cast<ICameraClient>(data.readStrongBinder());
                int32_t cameraId = data.readInt32();
                const String16 clientName = data.readString16();
                int32_t clientUid = data.readInt32();
                sp<ICamera> camera;
                status_t status = connect(cameraClient, cameraId,
                        clientName, clientUid, /*out*/camera);
                        //这里BnCameraService并没有实现connect函数,实际实现在CameraService中
                reply->writeNoException();
                reply->writeInt32(status);
                if (camera != NULL) {
                    reply->writeInt32(1);
                    reply->writeStrongBinder(camera->asBinder());
                } else {
                    reply->writeInt32(0);
                }
                return NO_ERROR;
            } break;
        ......
        }
     }

    我们来看一下CameraService中的connect方法到底做了哪些事情

    status_t CameraService::connect(
            const sp<ICameraClient>& cameraClient,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp<ICamera>& device) {
    
        String8 clientName8(clientPackageName);
        int callingPid = getCallingPid();
    
        LOG1("CameraService::connect E (pid %d "%s", id %d)", callingPid,
                clientName8.string(), cameraId);
        //对当前连接请求合法性的判断
        status_t status = validateConnect(cameraId, /*inout*/clientUid);
        if (status != OK) {
            return status;
        }
    
        //Client类继承BnCamera BasicClient
        sp<Client> client;
        {
            Mutex::Autolock lock(mServiceLock);
            sp<BasicClient> clientTmp;
            //判断当前设备是否被占有或者是重复请求
            if (!canConnectUnsafe(cameraId, clientPackageName,
                                  cameraClient->asBinder(),
                                  /*out*/clientTmp)) {
                return -EBUSY;//从返回结果可以看出这个函数的用途
            } else if (client.get() != NULL) {
                device = static_cast<Client*>(clientTmp.get());
                return OK;
            }
            //考虑当前没有其他程序占用摄像头,走到下一步
            status = connectHelperLocked(/*out*/client,
                                         cameraClient,
                                         cameraId,
                                         clientPackageName,
                                         clientUid,
                                         callingPid);
            if (status != OK) {
                return status;
            }
    
        }
        // 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作为传出参数
        device = client;
        return OK;
    }

    继续跟踪到connectHelperLocked()函数中

    status_t CameraService::connectHelperLocked(
            /*out*/
            sp<Client>& client,
            /*in*/
            const sp<ICameraClient>& cameraClient,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            int callingPid,
            int halVersion,
            bool legacyMode) {
    
        int facing = -1;
        int deviceVersion = getDeviceVersion(cameraId, &facing);
    
        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:
                //创建CameraClient对象
                client = new CameraClient(this, cameraClient,
                        clientPackageName, cameraId,
                        facing, callingPid, clientUid, getpid(), legacyMode);
                break;
              case CAMERA_DEVICE_API_VERSION_2_0:
              case CAMERA_DEVICE_API_VERSION_2_1:
              case CAMERA_DEVICE_API_VERSION_3_0:
              case CAMERA_DEVICE_API_VERSION_3_1:
              case CAMERA_DEVICE_API_VERSION_3_2:
                client = new Camera2Client(this, cameraClient,
                        clientPackageName, cameraId,
                        facing, callingPid, clientUid, getpid(), legacyMode);
                break;
              case -1:
                ALOGE("Invalid camera id %d", cameraId);
                return BAD_VALUE;
              default:
                ALOGE("Unknown camera device HAL version: %d", deviceVersion);
                return INVALID_OPERATION;
            }
        } 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.
                client = new CameraClient(this, cameraClient,
                        clientPackageName, cameraId,
                        facing, callingPid, clientUid, getpid(), 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 INVALID_OPERATION;
            }
        }
        //主要是对CameraClient的初始化过程
        status_t status = connectFinishUnsafe(client, client->getRemote());
        if (status != OK) {
            // this is probably not recoverable.. maybe the client can try again
            return status;
        }
        //保存CameraClient对象到本地数组中,以备CameraService使用
        mClient[cameraId] = client;
        LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
             getpid());
    
        return OK;
    }

    这里的client创建成功后会赋值给device,而device就是之前连接过程中的传入参数,到这里Camera的连接过程就基本完成了。

    本文主要顺着代码理了一下过程,具体细节地方可能有所忽略。主要的流程图如下,欢迎交流指正。

    这里写图片描述

    本文中代码使用的是Android5.1原始代码

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    appium 环境安装windows
    解决windows7无法连接CentOS7系统中oracle问题:ORA-12514 TNS 监听程序当前无法识别
    linux系统(CentOS7)虚拟机上安装oracle 11g,解决oracle图形界面卡住无法点击next问题
    python自动化测试框架学习
    VSCode + GDBServer 远程调试C/C++流水账
    IDEA 16注册
    VS2008非托管C++调用wcf(WebService)服务
    python 从数据库表生成model
    2015年工作总结
    dlib库学习之一
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6467219.html
Copyright © 2020-2023  润新知