Android5.0 Camera Framework 简介

###CameraService启动
CameraService是在MediaServer启动过程中进行的
main_mediaserver.cpp (frameworks\av\media\mediaserver)

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

在 main函数中会执行到CameraService::instantiate(), CameraService 本身并没有实现这个方法
CameraService.cpp (frameworks\av\services\camera\libcameraservice)
CameraService.h (frameworks\av\services\camera\libcameraservice)
BinderService.h (frameworks\native\include\binder)

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

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

templateclass BinderService{public:    static status_t publish(bool allowIsolated = false) { //BinderService::publish        sp 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 (frameworks\base\core\java\android\hardware)
Camera.cpp (frameworks\av\camera)
android_hardware_Camera.cpp (frameworks\base\core\jni)
从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(this), cameraId, halVersion, packageName);    }

可以看到native_setup是一个native方法,具体实现在
android_hardware_Camera.cpp (frameworks\base\core\jni)

static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,    jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName){    ......    sp 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 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 (frameworks\av\camera)
CameraBase.cpp (frameworks\av\camera)

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

CameraBase中connect函数模板替换成

sp CameraBase>::connect(int cameraId,                                               const String16& clientPackageName,                                               int clientUid){    ALOGV("%s: connect", __FUNCTION__);    sp c = new Camera(cameraId);    sp cl = c;    status_t status = NO_ERROR;    const sp& 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 这里TCam化成Camera应该比较清晰,而TCamTraits的替换,首先从CameraBase.h文件中看

template struct CameraTraits {};template  >

然后我们再到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 (frameworks\av\camera)

    // connect to camera service (android.hardware.Camera)    virtual status_t connect(const sp& cameraClient, int cameraId,                             const String16 &clientPackageName, int clientUid,                             /*out*/                             sp& 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(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 cameraClient =                    interface_cast(data.readStrongBinder());            int32_t cameraId = data.readInt32();            const String16 clientName = data.readString16();            int32_t clientUid = data.readInt32();            sp 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& 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;    }    //Client类继承BnCamera BasicClient    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;        }        //考虑当前没有其他程序占用摄像头,走到下一步        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,        /*in*/        const sp& 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原始代码

更多相关文章

  1. Ubuntu 编译Android若干错误及解决方法
  2. Android(安卓)Native 应用程序启动 Activity 的方法
  3. Android(安卓)Wifi Driver Porting
  4. 使用RecyclerView加载不出数据的原因可能有:
  5. android中禁止GridView上下滑动的方法
  6. 【Android】树形菜单、扩展下拉菜单BaseExpandableListAdapter、
  7. Android常用方法
  8. 罗列一些 android中的常用模块和方法
  9. Android(安卓)Service用法总结和生命周期详解

随机推荐

  1. mysql 5.7.20常用下载、安装和配置方法及
  2. Mac OS系统下mysql 5.7.20安装教程图文详
  3. Mysql 5.7.20压缩版下载和安装简易教程
  4. Android—高级组件对应属性大全及使用详
  5. Android获取屏幕高度、标题高度、状态栏
  6. Android的五大布局
  7. android.widget.TextView 属性详解
  8. Android(安卓)计步传感器的实现
  9. android 资源文件命名规则 drawable mipm
  10. Android学习笔记Android线程模型解析