Android4.4 Camera client连接到CameraService的过程分析

先抛出一张类图关系,纯手工制作,比较乱,不过看完文章后再来看这张图会很清晰:
Android4.4 Camera client连接到CameraService的过程分析_第1张图片

1.cameraservice在mediaservice中启动:

CameraService::instantiate();

先分析一下CameraService的继承类:

class CameraService :
    public BinderService,
    public BnCameraService,
    public IBinder::DeathRecipient,
    public camera_module_callbacks_t
{

1,第一个是BinderService,

会发现cameraservice其实并没有实现父类BinderService的方法instantiate();所以会调用父类的方法:

static void instantiate() { publish(); }

都是静态方法:

static status_t publish(bool allowIsolated = false) {
        sp sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }
static char const* getServiceName() { return "media.camera"; }

初始化得到一个sm实例,这里得到的也就是全局中唯一的servicemanager,向sm实例中添加cameraservice服务实例,到这里cameraservice成功注册到sm中,后续需要与cameraservice建立沟通只要向sm传入service name就能获取到这个cameraservice服务。这边传入的service name是:media.camera。

2.第二个继承的类 public BnCameraService,

BnCameraService/BpCameraService/ICameraService 三个类是第一个跟camera相关的binder框架之一,里面主要是上层快要启动camera 相关实际操作之前的跟camera一些交互包括获取camera id和连接到cameraservce这两个重要操作。

virtual int32_t  getNumberOfCameras() = 0;
    virtual status_t getCameraInfo(int cameraId,
                                          struct CameraInfo* cameraInfo) = 0;

    virtual status_t getCameraCharacteristics(int cameraId,
                                              CameraMetadata* cameraInfo) = 0;

    // Returns 'OK' if operation succeeded
    // - Errors: ALREADY_EXISTS if the listener was already added
    virtual status_t addListener(const sp& listener)
                                                                            = 0;
    // Returns 'OK' if operation succeeded
    // - Errors: BAD_VALUE if specified listener was not in the listener list
    virtual status_t removeListener(const sp& listener)
                                                                            = 0;
    /**
     * clientPackageName and clientUid are used for permissions checking.  if
     * clientUid == USE_CALLING_UID, then the calling UID is used instead. Only
     * trusted callers can set a clientUid other than USE_CALLING_UID.
     */
    virtual status_t connect(const sp& cameraClient,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp& device) = 0;

    virtual status_t connectPro(const sp& cameraCb,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp& device) = 0;

    virtual status_t connectDevice(
            const sp& cameraCb,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp& device) = 0;

cameraservice继承它,也就成为了这些接口的实现者。
这边看一下当上层准备启动camera应用来连接cameraservice的过程:
在camera.java中的open接口中:

 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;
    }

最先调用的jni函数是getNumberOfCameras(),获取camera的index,为后面打开camera设备做准备:
对应下面的JNI层接口在android_hardware_camera.cpp中,目录在base/core/jni文件夹下:

static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz)
{
    return Camera::getNumberOfCameras();
}

可以看到是通过静态调用方式,camera类并没有实现这个方法,而是父类CameraBase实现了:

int CameraBase::getNumberOfCameras() {
    const sp cs = getCameraService();

    if (!cs.get()) {
        // as required by the public Java APIs
        return 0;
    }
    return cs->getNumberOfCameras();
}

代码虽简洁,但都是干货:
const sp cs = getCameraService();这个操作获取目前的cameraservice在客户端这边的binder实例,获取这个实例也就是为了能够在客户端这边跨进程调用cameraservice的接口:

// establish binder interface to camera service
template <typename TCam, typename TCamTraits>
const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
{
    Mutex::Autolock _l(gLock);
    if (gCameraService.get() == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16(kCameraServiceName));
            if (binder != 0) {
                break;
            }
            ALOGW("CameraService not published, waiting...");
            usleep(kCameraServicePollDelay);
        } while(true);
        if (gDeathNotifier == NULL) {
            gDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(gDeathNotifier);
        gCameraService = interface_cast<ICameraService>(binder);
    }
    ALOGE_IF(gCameraService == 0, "no CameraService!?");
    return gCameraService;
}

看这个获取cameraservice的过程,先是通过defaultServiceManager()得到全局的sm service,然后通过servicename 去获取cameraservice,可以看到这里传入的name 变量:kCameraServiceName。这个在camerabase.h中声明:

const char*               kCameraServiceName      = "media.camera";

获取上来的是一个binder实例,通过binder->linkToDeath(gDeathNotifier);应该是向binder激活注册的意思。也就是第一套bidner框架就此激活。

接着把这个binder类型通过C++的强制转化成cameraservice的实例,就这样获取到了远程调用cameraservice接口的binder实例,建立起了ipc机制。

接着继续关注这个接口cs->getNumberOfCameras();最后这么调了下去,会调到cameraservice中的实现:

int32_t CameraService::getNumberOfCameras() {
    if(mNumberOfCameras == 0) {
       ALOGE("no camera found before! check again...");
       onFirstRef();
    }
    return mNumberOfCameras;
}

接着看onFirstRef();

void CameraService::onFirstRef()
{
    LOG1("CameraService::onFirstRef");

    BnCameraService::onFirstRef();

    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
                (const hw_module_t **)&mModule) < 0) {
        ALOGE("Could not load camera HAL module");
        mNumberOfCameras = 0;
    }
    else {
        ALOGI("Loaded \"%s\" camera module", mModule->common.name);
        mNumberOfCameras = mModule->get_number_of_cameras();
        if (mNumberOfCameras > MAX_CAMERAS) {
            ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
                    mNumberOfCameras, MAX_CAMERAS);
            mNumberOfCameras = MAX_CAMERAS;
        }
        for (int i = 0; i < mNumberOfCameras; i++) {
            setCameraFree(i);
        }

        if (mModule->common.module_api_version >=
                CAMERA_MODULE_API_VERSION_2_1) {
            mModule->set_callbacks(this);
        }

        CameraDeviceFactory::registerService(this);
    }
}

我们只关注跟camera相关的代码,虽然有一个if-else语句,但是两个都会运行到,if括号的条件:hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&mModule);通过camera ID向下获取hardware相关的handle信息;获取成功了会运行else的内容:
mNumberOfCameras = mModule->get_number_of_cameras();通过上面获取上来的handle与cameraHAL建立联系,向下调用接口所在的文件是cameraHAL_module.cpp,这里直接跳过了camerahardwareinterface.h这个接口层。到这里调到底层了。接下去继续看camera.java中这一操作的下一步骤:

第二个就是根据获取上来的index,去获取camera的info:getCameraInfo(i, cameraInfo);保存到实例cameraInfo中,过程和上面差不多,接着就准备实例化camera类。看看类构造函数:

    Camera(int cameraId) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
        mPreviewCallback = null;
        mPostviewCallback = null;
        mUsingPreviewAllocation = false;
        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;
        }

        String packageName = ActivityThread.currentPackageName();

        native_setup(new WeakReference(this), cameraId, packageName);
    }

比较重要的一部调用:
native_setup(new WeakReference(this), cameraId, packageName);对应JNI层接口:
这里给出C++-JAVA的接口对应,这边名字有点不一样:

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;ILjava/lang/String;)V",
    (void*)android_hardware_Camera_native_setup },
  { "native_release",
    "()V",
    (void*)android_hardware_Camera_release },
  { "setPreviewDisplay",
    "(Landroid/view/Surface;)V",
    (void *)android_hardware_Camera_setPreviewDisplay },
  { "setPreviewTexture",
    "(Landroid/graphics/SurfaceTexture;)V",
    (void *)android_hardware_Camera_setPreviewTexture },
  { "setPreviewCallbackSurface",
    "(Landroid/view/Surface;)V",
    (void *)android_hardware_Camera_setPreviewCallbackSurface },
  { "startPreview",
    "()V",
    (void *)android_hardware_Camera_startPreview },
  { "_stopPreview",
    "()V",
    (void *)android_hardware_Camera_stopPreview },
  { "previewEnabled",
    "()Z",
    (void *)android_hardware_Camera_previewEnabled },
  { "setHasPreviewCallback",
    "(ZZ)V",
    (void *)android_hardware_Camera_setHasPreviewCallback },
  { "_addCallbackBuffer",
    "([BI)V",
    (void *)android_hardware_Camera_addCallbackBuffer },
  { "native_autoFocus",
    "()V",
    (void *)android_hardware_Camera_autoFocus },
  { "native_cancelAutoFocus",
    "()V",
    (void *)android_hardware_Camera_cancelAutoFocus },
  { "native_takePicture",
    "(I)V",
    (void *)android_hardware_Camera_takePicture },
  { "native_setParameters",
    "(Ljava/lang/String;)V",
    (void *)android_hardware_Camera_setParameters },
  { "native_getParameters",
    "()Ljava/lang/String;",
    (void *)android_hardware_Camera_getParameters },
  { "reconnect",
    "()V",
    (void*)android_hardware_Camera_reconnect },
  { "lock",
    "()V",
    (void*)android_hardware_Camera_lock },
  { "unlock",
    "()V",
    (void*)android_hardware_Camera_unlock },
  { "startSmoothZoom",
    "(I)V",
    (void *)android_hardware_Camera_startSmoothZoom },
  { "stopSmoothZoom",
    "()V",
    (void *)android_hardware_Camera_stopSmoothZoom },
  { "setDisplayOrientation",
    "(I)V",
    (void *)android_hardware_Camera_setDisplayOrientation },
  { "_enableShutterSound",
    "(Z)Z",
    (void *)android_hardware_Camera_enableShutterSound },
  { "_startFaceDetection",
    "(I)V",
    (void *)android_hardware_Camera_startFaceDetection },
  { "_stopFaceDetection",
    "()V",
    (void *)android_hardware_Camera_stopFaceDetection},
  { "enableFocusMoveCallback",
    "(I)V",
    (void *)android_hardware_Camera_enableFocusMoveCallback},
};

可以看到native_setup对应的是:

// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jstring clientPackageName)
{
    // Convert jstring to String16
    const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL);
    jsize rawClientNameLen = env->GetStringLength(clientPackageName);
    String16 clientName(rawClientName, rawClientNameLen);
    env->ReleaseStringChars(clientPackageName, rawClientName);

    sp<Camera> camera = Camera::connect(cameraId, clientName,
            Camera::USE_CALLING_UID);

    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.
    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
    context->incStrong((void*)android_hardware_Camera_native_setup);
    camera->setListener(context);

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

从这里开始camera开始真正的一系列初始化操作:

sp camera = Camera::connect(cameraId, clientName,
            Camera::USE_CALLING_UID);

这里开始连接到cameraservice,由于还没建立好service连接,所以这里还是调用前面的一套binder框架:

template 
sp CameraBase::connect(int cameraId,
                                               const String16& clientPackageName,
                                               int clientUid)
{
    ALOGV("%s: connect", __FUNCTION__);
    sp c = new TCam(cameraId);
    sp cl = c;
    status_t status = NO_ERROR;
    const sp& cs = getCameraService();

    if (cs != 0) {
        TCamConnectService fnConnectService = TCamTraits::fnConnectService;
        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 <>
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;
};

这样我把这些替换进去:

 ALOGV("%s: connect", __FUNCTION__);
    sp c = new Camera(cameraId);
    sp cl = c;
    status_t status = NO_ERROR;
    const sp& cs = getCameraService();

    if (cs != 0) {
        TCamConnectService fnConnectService = TCamTraits::fnConnectService;
        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;

这样一看初始化一个camera 实例,然后赋值给ICameraClient类对象c1,这里又有一个以IXXX类型的接口,说明又涉及到了binder框架,这就是camera的第二套binder框架,主要是用来底层回调callback给上层用的:
ICameraClient/BnCameraClient/BpCameraClient
Camera 继承BnCameraClient类,所以回调上来的callback都在camera类中实现作为底层(cameraservice)的服务端,这里把c1实例作为参数传到底层,就是为了和底层建立联系。

获取到cameraservice实例之后,

TCamConnectService fnConnectService = TCamTraits::fnConnectService;
        status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
                                             /*out*/ c->mCamera);

这两句代码的意思简单讲就是调用了ICameraService里的connect接口。关键看camera.cpp中一举初始化:

CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
        &ICameraService::connect;

上面这句代码把ICameraService::connect的函数指针赋值给了fnConnectService。最后就会往下一直调用到cameraservice.cpp中的connect接口,至于这边为什么写的这么隐晦,目前没看懂,后面有时间会关注一下。留意下/out/ c->mCamera这个参数,这是穿进去了一个地址,经过下面走一趟之后,会获得到底层cameraservice的binder对象,后面被保存到camerabase的成员变量中,这样后面的camera操作就可以通过这个binder对象来和cameraservice接口进行联通了。

接下来看ICameraService中connect的实现:

// 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);

        if (readExceptionCode(reply)) return -EPROTO;
        status_t status = reply.readInt32();
        if (reply.readInt32() != 0) {
            device = interface_cast<ICamera>(reply.readStrongBinder());
        }
        return status;
    }

当中往下调用成功后:if (reply.readInt32() != 0) {
device = interface_cast(reply.readStrongBinder());
}
会从reply的binder包里保存得到ICamera的实例,就如下面所说这个实例会被保存到java全局中,而保证只有一个camera实例存在。

看一下cameraservice中connect的实现:

status_t CameraService::connect(
        const sp& cameraClient,
        int cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp& 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;
    }


    sp client;
    {
        Mutex::Autolock lock(mServiceLock);
        sp clientTmp;
        if (!canConnectUnsafe(cameraId, clientPackageName,
                              cameraClient->asBinder(),
                              /*out*/clientTmp)) {
            return -EBUSY;
        } else if (client.get() != NULL) {
            device = static_cast(clientTmp.get());
            return OK;
        }

        int facing = -1;
        int deviceVersion = getDeviceVersion(cameraId, &facing);

        // If there are other non-exclusive users of the camera,
        //  this will tear them down before we can reuse the camera
        if (isValidCameraId(cameraId)) {
            // transition from PRESENT -> NOT_AVAILABLE
            updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
                         cameraId);
        }

        switch(deviceVersion) {
          case CAMERA_DEVICE_API_VERSION_1_0:
            client = new CameraClient(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid());
            break;
          case CAMERA_DEVICE_API_VERSION_2_0:
          case CAMERA_DEVICE_API_VERSION_2_1:
          case CAMERA_DEVICE_API_VERSION_3_0:
            client = new Camera2Client(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid(),
                    deviceVersion);
            break;
          case -1:
            ALOGE("Invalid camera id %d", cameraId);
            return BAD_VALUE;
          default:
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
            return INVALID_OPERATION;
        }

        status_t status = connectFinishUnsafe(client, client->getRemote());
        if (status != OK) {
            // this is probably not recoverable.. maybe the client can try again
            // OK: we can only get here if we were originally in PRESENT state
            updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId);
            return status;
        }

        mClient[cameraId] = client;
        LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
             getpid());
    }
    // 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 OK;
}

connect的接口主要完成以下几件事,先是判断连接是否安全

if (!canConnectUnsafe(cameraId, clientPackageName,
                              cameraClient->asBinder(),
                              /*out*/clientTmp)) 

这个if语句会防止有两个camera client连接到同一个camera service中来,过了这关,会调用getDeviceVersion的接口获取底层的device版本,进而选取实例化的cameraclient的类,这个类很重要,里面实现了camera上层传下来的各种操作,比如startPreview,setPreviewWindow等一下camera启动后的设置操作。

case CAMERA_DEVICE_API_VERSION_1_0:
            client = new CameraClient(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid());

传入了一个参数:cameraClient,这是上层cameraclient的实例的binder对象,这里传到底层,也就是为了底层能够和上层进行通信,其实就是底层抛callback给上层,前面有说到过,进一步跟踪cameraclient的构造函数,父类保存了实例:mRemoteCallback = cameraClient;其祖父类也保存了在BasicClient中mRemoteBinder = remoteCallback。既然保存好了,binder的实例是需要激活的,就像前面的通过sm获取到一个cameraservice实例一样,这边的激活是在下面connectFinishUnsafe中实现的,下面会提到。 好了保存这个怎么用了?肯定是回调的时候要获取到这个实例,然后通过binder框架回调到上层的camera类中的datacallback。我们简单看下datacallback回调过程中的一个接口:

// picture callback - postview image ready
void CameraClient::handlePostview(const sp<IMemory>& mem) {
    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);

    sp<ICameraClient> c = mRemoteCallback;
    mLock.unlock();
    if (c != 0) {
        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
    }
}

可以很清楚的看到,显示初始化得到一个ICameraClient实例,而这个实例就是我们刚才千辛万苦从上层传下来然后保存到底层的远程binder实例,通过这个就可以调用上层接口了。继续分析connect过程。
最后检查连接完成后是否安全

status_t status = connectFinishUnsafe(client, client->getRemote());
status_t CameraService::connectFinishUnsafe(const sp& client,
                                            const sp& remoteCallback) {
    status_t status = client->initialize(mModule);
    if (status != OK) {
        return status;
    }

    remoteCallback->linkToDeath(this);

    return OK;
}

在这里会调用cameraclient类中初始化操作,主要工作就是打开Camera的硬件设备,并初始化好hardware到service的操作接口映射,还会注册三个重要的callback:dataCallback,notifyCallback,dataCallbackTimeStamp,具体过程请看前面的文章callback注册和回调过程。初始化完成后,把传进来的binder实例参数client->getRemote(),跟踪一下实现:

        // Return the remote callback binder object (e.g. IProCameraCallbacks)
        sp     getRemote() {
            return mRemoteBinder;
        }

返回的正是我们在上面保存的上层cameraclient的实例的binder对象,然后通过 remoteCallback->linkToDeath(this);来激活注册这个binder框架。也就是第二套框架binder框架,专门用来底层回调函数用的。

connect的最后一步,保存刚才创建的的cameraclient实例:

 mClient[cameraId] = client;

并赋值:device = client;这一步赋值,是为了能够让上层得到cameraservice的binder实例,为了建立联系。

这边返回到上面camerabase中的connect接口:

template 
sp CameraBase::connect(int cameraId,
                                               const String16& clientPackageName,
                                               int clientUid)
{
    ALOGV("%s: connect", __FUNCTION__);
    sp c = new TCam(cameraId);
    sp cl = c;
    status_t status = NO_ERROR;
    const sp& cs = getCameraService();

    if (cs != 0) {
        TCamConnectService fnConnectService = TCamTraits::fnConnectService;
        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;
}

当我们调用玩connect接口后,返回回来的就是 c->mCamera;
接下会进到if分之:

if (status == OK && c->mCamera != 0) {
        c->mCamera->asBinder()->linkToDeath(c);
        c->mStatus = NO_ERROR;
    } 

通过linkToDeath激活这个binder框架:
这个操作建立起了cameraservice第三套binder框架接口:
BnCamera ,BpCamera,ICamera
其中CameraService::Client 继承BnCamera类作为服务端,而真正实现接口的是CameraService::Client::CameraClient类。
到这里连接结束,也建立起了上层和cameraservice之间的接口桥梁-binder。后面对camera的操作都会通过这个桥梁来进行,主要相关的类为:CameraService::Client::CameraClient BnCamera BpCamera Camera .
,至此camera的第三套binder框架也被激活。

这里继续回到JNI接口android_hardware_Camera_native_setup中进行分析初始化过程:
连接成功后会对hardware做以下检查确认:

 // 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;
    }

没有问题,接下来会初始化和保存一些比较重要的全局环境变量和实例:

sp context = new JNICameraContext(env, weak_this, clazz, camera);
    context->incStrong((void*)android_hardware_Camera_native_setup);
    camera->setListener(context);

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

第一行是JNICameraContext类对象的初始化,这个类主要是为了底层callback上来后,如何传到java空间的接口操作:

class JNICameraContext: public CameraListener
{
public:
    JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp& camera);
    ~JNICameraContext() { release(); }
    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
    virtual void postData(int32_t msgType, const sp& dataPtr,
                          camera_frame_metadata_t *metadata);
    virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr);
    void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata);
    void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType);
    void setCallbackMode(JNIEnv *env, bool installed, bool manualMode);
    sp getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
    bool isRawImageCallbackBufferAvailable() const;
    void release();

private:
    void copyAndPost(JNIEnv* env, const sp& dataPtr, int msgType);
    void clearCallbackBuffers_l(JNIEnv *env, Vector *buffers);
    void clearCallbackBuffers_l(JNIEnv *env);
    jbyteArray getCallbackBuffer(JNIEnv *env, Vector *buffers, size_t bufferSize);


    sp  mCamera;                // strong reference to native object

    //去掉了一些代码......
    Vector mCallbackBuffers; // Global reference application managed byte[]
    bool mManualBufferMode;              // Whether to use application managed buffers.
    bool mManualCameraCallbackSet;       // Whether the callback has been set, used to
                                         // reduce unnecessary calls to set the callback.
};

,比如前面文章介绍的dataCallback,传到JNI层会调用postData,copyAndPost等接口,notifyCallback则会调用到notify接口。里面还保存了全局camera对象实例sp mCamera;可以看下构造函数:

JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera)
{
    mCameraJObjectWeak = env->NewGlobalRef(weak_this);
    mCameraJClass = (jclass)env->NewGlobalRef(clazz);
    mCamera = camera;

    jclass faceClazz = env->FindClass("android/hardware/Camera$Face");
    mFaceClass = (jclass) env->NewGlobalRef(faceClazz);

    jclass rectClazz = env->FindClass("android/graphics/Rect");
    mRectClass = (jclass) env->NewGlobalRef(rectClazz);

    mManualBufferMode = false;
    mManualCameraCallbackSet = false;
}

后面的JNI接口想要调用camera的一些接口必然会需要到camera实例,针对一个camera设备只有一个实例,所以在第一次初始化后就会被保存到这个JNI Camera上下文中,需要时调用接口去获取即可。

接下来就是设置listener,这个listener就是用来监听底层的callback消息,他的初始化是这里完成的。

最后保存这个上下文到一个区域里,暂时没清楚其原理,后续会继续研究。

我们来看一下,这边是怎么获取这个被保存的camera实例:
比如常用的startPreview接口:

static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
{
    ALOGV("startPreview");
    sp camera = get_native_camera(env, thiz, NULL);
    if (camera == 0) return;

    if (camera->startPreview() != NO_ERROR) {
        jniThrowRuntimeException(env, "startPreview failed");
        return;
    }
}

sp camera = get_native_camera(env, thiz, NULL);会调用到本地的一个接口:

sp get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext)
{
    sp camera;
    Mutex::Autolock _l(sLock);
    JNICameraContext* context = reinterpret_cast(env->GetIntField(thiz, fields.context));
    if (context != NULL) {
        camera = context->getCamera();
    }
    ALOGV("get_native_camera: context=%p, camera=%p", context, camera.get());
    if (camera == 0) {
        jniThrowRuntimeException(env, "Method called after release()");
    }

    if (pContext != NULL) *pContext = context;
    return camera;
}

通过初始化context,通过传进去的java虚拟机 环境变量 env和thiz从一个域里面获取 JNI camera 的上下文,然后再从这个context实例中获取camera 的实例:camera = context->getCamera();最后返回这个实例。

3.第三个继承的类 public IBinder:: DeathRecipient

这个其实就是跟binder框架相关了,需要继承这个类来满足binder框架的一些机制,这里不做研究。

4.第四个继承的类 public camera_module_callbacks_t

继承这个类后再onFirstRef中mModule->set_callbacks(this);传入的this指针就没有什么异议了,CameraService同为camera_module_callbacks_t类型。

你可能感兴趣的:(Linux,Android,C/C++)