Camera 的开始过程

应用程序链接相机服务过程:

    camera应用程序启动的时候首先会和CameraService建立连接,camera应用程序代码就不分析了,下面这幅图是一个简单的流程图,从别人哪儿拿过来的:

Camera 的开始过程_第1张图片

1-1:照相机应用程序启动流程图

    从上面的流程图我们可以看出在请求服务的过程中多出用到了应用框架层的camera,该类定义在frameworks/base/core/java/android/hardware/Camera.java文件当中,这一个类正是Camera子系统中APP层和JNI层交换的接口,它对上为应用程序提供了各种操作Camera的方法,向下访问JNI实现它自身的接口Camera类定义如下:

 public static Camera open(int cameraId) {
        return new Camera(cameraId);
    }

    /**
     * Creates a new Camera object to access the first back-facing camera on the
     * device. If the device does not have a back-facing camera, this returns
     * null.
     * @see #open(int)
     */
    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;
    }

    Camera(int cameraId) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
        mPreviewCallback = null;
        mPreviewRawDumpCallback = null;
        mPostviewCallback = null;
        mZoomListener = null;

        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else if ((looper = Looper.getMainLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else {
            mEventHandler = null;
        }

        native_setup(new WeakReference<Camera>(this), cameraId);
    }


Camera.open(intcameraId) 方法调用 native_setup 本地方法 , 其中 native_setup 本地方法在 JNI层被注册成如下方法:

frameworks/base/core/jni/android_hardware_Camera.cpp

static JNINativeMethod camMethods[] = {
  { "getNumberOfCameras",
    "()I",
    (void *)android_hardware_Camera_getNumberOfCameras },
  { "_getCameraInfo",
    "(ILandroid/hardware/Camera$CameraInfo;)V",
    (void*)android_hardware_Camera_getCameraInfo },
  { "native_setup",
    "(Ljava/lang/Object;I)V",
    (void*)android_hardware_Camera_native_setup },
  { "native_release",
    "()V",
    (void*)android_hardware_Camera_release },
  ……
 -----------------------------------------------------------------------------
};


(3)native_setup函数通过JNI调用android_hardware_Camera_native_setup函数,该函数的实现如下://通过android_hardware_Camera_native_setup请求CameraService

// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId)
{
    sp<Camera> camera = Camera::connect(cameraId);

    if (camera == NULL) {
        jniThrowRuntimeException(env, "Fail to connect to camera service");
        return;
    }

    // make sure camera hardware is alive
    if (camera->getStatus() != NO_ERROR) {
        jniThrowRuntimeException(env, "Camera initialization failed");
        return;
    }

    jclass clazz = env->GetObjectClass(thiz);
    if (clazz == NULL) {
        jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
        return;
    }

    // We use a weak reference so the Camera object can be garbage collected.
    // The reference is only used as a proxy for callbacks.
//!++
#ifdef  MTK_CAMERA_BSP_SUPPORT
    sp<JNICameraContext> context = new MtkJNICameraContext(env, weak_this, clazz, camera);
#else
    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
#endif
//!--
    context->incStrong(thiz);
    camera->setListener(context);

    // save context in opaque field
    env->SetIntField(thiz, fields.context, (int)context.get());
} 


(4)android_hardware_Camera_native_setup通过调用Camera::connect(intcameraId)函数请求连接服务。frameworks/av/camera/camera.cpp

    sp<Camera> Camera::connect(int cameraId)
    {
        ALOGV("connect");
        sp<Camera> c = new Camera();//BnCameraClient
        const sp<ICameraService>& cs = getCameraService();//return BpCameraService
        if (cs != 0) {//Used for processing all kinds of events
            c->mCamera = cs->connect(c, cameraId);//return
        }
        if (c->mCamera != 0) {
            c->mCamera->asBinder()->linkToDeath(c);
            c->mStatus = NO_ERROR;
        } else {
            c.clear();
        }
        return c;
    }


(5)Camera::connect(intcameraId)函数首先向ServiceManager获取Camera服务信息,并生成CameraService服务代理BpCameraService,然后通过Binder通信发送CONNECT命令,BnCameraService收到CONNECT命令后调用CameraServiceconnect()成员函数来做相应的处理,接下来我们就分析CameraServiceconnect()成员函数,注意在这一步骤中首先new了一个Camera本地实例,这个Camera类是BnCameraClient的子类,在调用BpCameraService::connect的时候我们将新生成的Camera做为参数传递给了CameraService.我们先来看BpCameraServiceconnect函数

    class BpCameraService: public BpInterface<ICameraService>
    {
    public:
        // connect to camera service
        virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId)
        {
            Parcel data, reply;
            data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
            data.writeStrongBinder(cameraClient->asBinder());//转换成IBinder类型
            data.writeInt32(cameraId);
            remote()->transact(BnCameraService::CONNECT, data, &reply);
            return interface_cast<ICamera>(reply.readStrongBinder());//BpCamera
        }
    };


    首先将我们传递过来的Camera对象转换成IBinder类型,然后由BnCameraService去响应该连接,最后就是等待服务端返回,如果成功这里为我们生成一个BpCamera实例,怎么来的下面继续分析,接收服务命令的代码段如下:

    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 =//(a)
                     interface_cast<ICameraClient>(data.readStrongBinder());
             //return Client 继承BnCamera
                sp<ICamera> camera = connect(cameraClient, data.readInt32());//(b)
                reply->writeStrongBinder(camera->asBinder());//(c)
                return NO_ERROR;
            } break;
            default:
                return BBinder::onTransact(code, data, reply, flags);
        }
    }

    服务端接到CONNECT命令之后开始进行一系列的类型转换,先看代码段(a)还记得之前我们传递过来的是Camera实例,Camera继承了BnCameraClient,所以在(a),使用CameraBinder对象为我们生成了Camera服务代理BpCameraClient实例

    (b)将生成的BpCameraClient对象作为参数打包到CameraServiceconnect()函数中,至于这个connect函数做了什么,先不管.先看(c)

    (c)将在(b)中返回的实例对象以IBinder的形式返回,现在再回到BpCameraService::connect函数的最后一句returninterface_cast<ICamera>(reply.readStrongBinder()),是不是明白了?如果在(c)中成功创建了一个Client实例对象,(ClientBnCamera的子类),那么在BpCameraService::connect函数中是不是会为我们返回一个BpCamera对象?yes!为了验证我们来分析CameraServiceconnect()成员函数frameworks/av/services/camera/libcameraservice/CameraService.cpp

    sp<ICamera> CameraService::connect(
            const sp<ICameraClient>& cameraClient, int cameraId) {
        int callingPid = getCallingPid();
        LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
        if (!mModule) {/*在服务初始化的时候就已经获得了*/
            ALOGE("Camera HAL module not loaded");
            return NULL;
        }
        sp<Client> client;
        if (cameraId < 0 || cameraId >= mNumberOfCameras) {
            ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
                callingPid, cameraId);
            return NULL;
        }
        char value[PROPERTY_VALUE_MAX];
        /*策略相关*/
        property_get("sys.secpolicy.camera.disabled", value, "0");
        if (strcmp(value, "1") == 0) {
            // Camera is disabled by DevicePolicyManager.
            ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
            return NULL;
        }
        Mutex::Autolock lock(mServiceLock);
        /*这是CameraService类中的一个成员变量是用来记录摄像头设备的,并且
         *它是一个数组wp<Client> mClient[MAX_CAMERAS];每一个设备都对应一个Client
         */
        if (mClient[cameraId] != 0) {//第一次来的是应该是为空的,所以不会走这条分支
            client = mClient[cameraId].promote();
            if (client != 0) {
                if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
                    LOG1("CameraService::connect X (pid %d) (the same client)",
                         callingPid);
                    return client;
                } else {
                    ALOGW("CameraService::connect X (pid %d) rejected
                                    (existing client).",callingPid);
                    return NULL;
                }
            }
            mClient[cameraId].clear();
        }
        if (mBusy[cameraId]) {/*如果这设备ID处于忙状态*/
            ALOGW("CameraService::connect X (pid %d) rejected"
                    " (camera %d is still busy).", callingPid, cameraId);
            return NULL;
        }
        /*这个结构是硬件抽象范畴的,里面包含了一些基本信息
         * 其中facing描述前置还是后置
         * orientation 用来描述image方向
         * device_version用来描述HAL的版本
         */
        struct camera_info info;
        if (mModule->get_camera_info(cameraId, &info) != OK) {
            ALOGE("Invalid camera id %d", cameraId);
            return NULL;
        }
        int deviceVersion;
        if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) {
            deviceVersion = info.device_version;
        } else {
            deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
        }
        /*根据HAL不同API的版本创建不同的client实例,在之前版本中不是这样的,这是4.2的变化*/
        switch(deviceVersion) {
          case CAMERA_DEVICE_API_VERSION_1_0:
            client = new CameraClient(this, cameraClient, cameraId,
                    info.facing, callingPid, getpid());
            break;
          case CAMERA_DEVICE_API_VERSION_2_0://for 4.2
            client = new Camera2Client(this, cameraClient, cameraId,
                    info.facing, callingPid, getpid());
            break;
          default:
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
            return NULL;
        }
        /*初始化camera_module_t *module*/
        if (client->initialize(mModule) != OK) {
            return NULL;
        }
        cameraClient->asBinder()->linkToDeath(this);
        //最后将创建的CameraClient或Camera2Client实例保存到mClient[MAX_CAMERAS]数组当中去
        //mClient[MAX_CAMERAS]数组是CameraService类中的成员变量
        mClient[cameraId] = client;//every camera is a Client class
        LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
        return client;/*最后返回*/
    }

你可能感兴趣的:(Camera 的开始过程)