Android_JellyBean 4.2.1 Camera Service 請求過程分析

Camera子系統採用C/S架構,客戶端和服務端在兩個不一樣的進程當中,它們使用android中的binder機制進行通訊,本系列文章將從Android Camera應用程序到硬件抽象的實現一步一步對照相機系統進行分析,首先從CameraService初始化過程着手,而後從上層APP打開照相機->進行preview->拍照以及聚焦等功能的實現全面的學習照相機子系統 java

1 CameraService初始化過程 android

    frameworks/av/media/mediaserverMain_mediaserver.cpp, api

    CameraServiceMediaServer中初始化,下面代碼是MediaServermain函數,在該函數中初始化照相機服務 數組

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    .................
    CameraService::instantiate();
    ............
    IPCThreadState::self()->joinThreadPool();
}

CameraService中的instantiate方法用來建立CameraService實例,並進行相應的初始化,這個函數定義在它的父類BinderService中:frameworks/native/include/binder/BinderService.h,替換以後見以下代碼: 架構


class BinderService
{
public:
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return  sm->addService(String16(CameraService::getServiceName()),
                           new CameraService(), allowIsolated);
    }
    ...................
    static void instantiate() { publish(); }
    ...................
};
相機服務的初始化過程首先是建立CameraService實例,而後將其註冊到ServiceManager,關於它的啓動是發生在init.rc,經過media_server來啓動CameraService,具體代碼以下:

system/rootdir/init.rc 框架

service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm


service media /system/bin/mediaserver
    class main
    user media
    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc
    ioprio rt 4
cameraService註冊以及啓動過程當中cameraService自身會執行一些初始化的工做,主要涉及到以下工做


frameworks/av/services/camera/libcameraservice/CameraService.cpp

static CameraService *gCameraService;

CameraService::CameraService():mSoundRef(0), mModule(0)
{
    ALOGI("CameraService started (pid=%d)", getpid());
    gCameraService = this;
}


void 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 {/*最大支持兩個攝像頭*/
        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);
        }
     }
}

在上述初始化代碼中,先經過調用HAL硬件抽象層庫,獲取支持的攝像頭個數並保存到mNumberOfCameras 函數

2 應用程序連接相機服務過程 oop

     camera應用程序啓動的時候首先會和CameraService創建鏈接,camera應用程序代碼就不分析了,下面這副圖是一個簡單的流程圖,畫得有點醜 學習

2-1:照相機應用程序啓動流程圖 ui


    從上面的流程圖咱們能夠看出在請求服務的過程當中多出用到了應用框架層的camera,該類定義在 frameworks/base/core/java/android/hardware/Camera.java文件當中,這一個類正是Camera子系統中APP層和JNI層交換的接口,它對上爲應用程序提供了各類操做Camera的方法,向下訪問JNI實現它自身的接口Camera類定義以下:
public class Camera {
    public static Camera open(int cameraId) {
         return new Camera(cameraId);
    }

    Camera(int cameraId) {
        .................
        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);
     }
}

在分析框架源碼以前,先讓咱們瞭解一下應用程序請求服務以及服務處理示意圖:

2-2:照相機服務請求示意圖


接下來按照上面5個步驟來分析具體的源碼,其中地一個步驟的源碼在上一步中已解釋(2)Camera open(int cameraId)方法調用native_setup本地方法,其中native_setup本地方法在JNI層被註冊成以下方法:

frameworks/base/core/jni/android_hardware_Camera.cpp

static JNINativeMethod camMethods[] = {
{ 
"native_setup","(Ljava/lang/Object;I)V", (void*)android_hardware_Camera_native_setup },/*經過Camera.cpp鏈接CameraService*/
    …...
};

(3)native_setup函數經過JNI調用android_hardware_Camera_native_setup函數,該函數的實現以下://經過android_hardware_Camera_native_setup請求CameraService

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.
    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
    context->incStrong(thiz);
    camera->setListener(context);
    //將這一步驟返回的BpCameraClient返回到JAVA應用程序框架
    // save context in opaque field
    env->SetIntField(thiz, fields.context, (int)context.get());
}

(4)android_hardware_Camera_native_setup經過調用Camera::connect(int cameraId)函數請求鏈接服務。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(int cameraId)函數首先向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函數的最後一句return interface_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;/*最後返回*/
}

首先經過該函數咱們能夠驗證上面的(c)觀點,經過CameraService生成CameraService::Client服務代理BpCamera,下面看看Client類之間的關係圖

2-2:照相機服務請求示意圖2

相關文章
相關標籤/搜索