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

本文深入剖析Android 4.4中CameraService的启动过程,从cameraservice在mediaservice中的启动,到BinderService、BnCameraService的继承关系,再到与CameraService的交互,详细解释了上层应用如何通过Binder框架连接到CameraService,涉及到多个Binder框架的使用,以及Camera模块的初始化和硬件设备的交互。
摘要由CSDN通过智能技术生成

先抛出一张类图关系,纯手工制作,比较乱,不过看完文章后再来看这张图会很清晰:
这里写图片描述

1.cameraservice在mediaservice中启动:

CameraService::instantiate();

先分析一下CameraService的继承类:

class CameraService :
    public BinderService<CameraService>,
    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<IServiceManager> 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<ICameraServiceListener>& 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<ICameraServiceListener>& 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<ICameraClient>& cameraClient,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp<ICamera>& device) = 0;

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

    virtual status_t connectDevice(
            const sp<ICameraDeviceCallbacks>& cameraCb,
            int cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp<ICameraDeviceUser>& 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<TCam, TCamTraits>::getNumberOfCameras() {
    const sp<ICameraService> 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实例,

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值