Android4.2.2 CameraService服務啟動和應用端camera初始化記錄

來源:互聯網
上載者:User

之前的10篇博文主要是記錄了Android4.2.2的SurfaceFlinger的相關內容,為何之前會投入那麼多的時間,原因就在於之前在看camera的架構時,遇到了本地的ANativeWindow和Surface的內容。而這些是SurfaceFlinger中最常見的應用端的使用品。故而在學習完了SurfaceFlinger之後就來看看Camera的的架構內容。這裡先和大家分享android4.2.2的CameraService的啟動過程與其的架構。

1.cameraService在何處啟動

mediaserver啟動了我們cameraservice,即所謂的多媒體相關的服務總管。

int main(int argc, char** argv){    signal(SIGPIPE, SIG_IGN);    sp proc(ProcessState::self());    sp sm = defaultServiceManager();    ALOGI("ServiceManager: %p", sm.get());    AudioFlinger::instantiate();//多媒體服務的啟動包括音頻,網路攝影機等    MediaPlayerService::instantiate();    CameraService::instantiate();    AudioPolicyService::instantiate();    ProcessState::self()->startThreadPool();    IPCThreadState::self()->joinThreadPool();}

之前的文章有提到過一般的Service的啟動方式,這裡是典型的一種BinderService的啟動

class BinderService{public:    static status_t publish(bool allowIsolated = false) {        sp sm(defaultServiceManager());        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);    }    static void publishAndJoinThreadPool(bool allowIsolated = false) {        sp sm(defaultServiceManager());        sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);        ProcessState::self()->startThreadPool();        IPCThreadState::self()->joinThreadPool();    }    static void instantiate() { publish(); }//兩種初始化binder服務的方式    static status_t shutdown() {        return NO_ERROR;    }};

CameraService::CameraService():mSoundRef(0), mModule(0){    ALOGI("CameraService started (pid=%d)", getpid());    gCameraService = this;}void CameraService::onFirstRef()//camerservice產生sp後被調用{    BnCameraService::onFirstRef();    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,                (const hw_module_t **)&mModule) < 0) {//擷取並載入mModule變數,實際的hal層的硬體庫camera.fiber.so,載入了模組        ALOGE("Could not load camera HAL module");        mNumberOfCameras = 0;    }    else {        mNumberOfCameras = mModule->get_number_of_cameras();//通過hal擷取camera的數目        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);        }    }}

調用CameraService的建構函式後,會自動執行onFirstRef().在該函數內部主要實現了對Camera的Hal層的操作。

通過hw_get_module()獲得載入HAL層的模組控制代碼到mModule成員變數之中,並獲得硬體的Camera的個數到mNumberOfCameras之中。可以看到CameraService比起SurfaceFinger這個強大的service來說簡單了很多。

step3,camera用戶端的建立

通java層的new Camera()來到JNI層,依次經過camera.java再到本地JNI的android_hardware_Camera.cpp。

camera.java中Camera.open()函數的執行

   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中的類

    Camera(int cameraId) {        mShutterCallback = null;        mRawImageCallback = null;        mJpegCallback = null;        mPreviewCallback = null;        mPostviewCallback = null;        mZoomListener = null;        Looper looper;        if ((looper = Looper.myLooper()) != null) {.....        native_setup(new WeakReference(this), cameraId);    }

JNI層的android_hardware_camera.cpp中:

// connect to camera servicestatic void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,    jobject weak_this, jint cameraId){    sp camera = Camera::connect(cameraId);//調用Camera的connect函數    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;    }......}

來到Camera應用程式層的類connect函數,目標是請求CameraService建立一個Camera用戶端。

step4:camera用戶端的connect函數

sp Camera::connect(int cameraId){    ALOGV("connect");    sp c = new Camera();//BnCameraClient    const sp& cs = getCameraService();//擷取一個Bpcamerservice    if (cs != 0) {        c->mCamera = cs->connect(c, cameraId);//基於binder驅動最終會去調用camerservice側的connect,mCamera指向一個Bpcamera    }    if (c->mCamera != 0) {        c->mCamera->asBinder()->linkToDeath(c);        c->mStatus = NO_ERROR;    } else {        c.clear();    }    return c;}

建立一個應用端的Camera,該類class Camera : public BnCameraClient, public IBinder::DeathRecipient繼承關係如下。

cs = getCameraService()通過SM擷取CameraService在本地的一個代理。調用connect函數後最終調用CameraService側的connect()函數。

    virtual sp connect(const sp& cameraClient, int cameraId)    {        Parcel data, reply;        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());        data.writeStrongBinder(cameraClient->asBinder());        data.writeInt32(cameraId);//發送到服務端的資料包        remote()->transact(BnCameraService::CONNECT, data, &reply);//實際調用的是Bpbinder的transact        return interface_cast(reply.readStrongBinder());//傳入Bpbinder的handle數值返回一個new BpCamera,實際是服務端的Bncamera    }};

在這裡可以看到這邊傳入一個本地Camera類對象即new Camera(),這個匿名的binder對象將通過Binder驅動傳遞給CameraService。主要用於後續CameraService的回調給應用程式層的Camera來處理

step5:CameraSevice端的connect函數

sp CameraService::connect(        const sp& 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;    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);    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]) {        ALOGW("CameraService::connect X (pid %d) rejected"                " (camera %d is still busy).", callingPid, cameraId);        return NULL;    }    struct camera_info info;    if (mModule->get_camera_info(cameraId, &info) != OK) {//擷取camera的相關資訊        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;    }    switch(deviceVersion) {      case CAMERA_DEVICE_API_VERSION_1_0:        client = new CameraClient(this, cameraClient, cameraId,                info.facing, callingPid, getpid());//client是CameraClient的基類,建立一個camerservice側的cameraclient        break;      case CAMERA_DEVICE_API_VERSION_2_0:        client = new Camera2Client(this, cameraClient, cameraId,                info.facing, callingPid, getpid());        break;      default:        ALOGE("Unknown camera device HAL version: %d", deviceVersion);        return NULL;    }    if (client->initialize(mModule) != OK) {//cameraclient init初始化,實際調用的是CameraClient        return NULL;    }    cameraClient->asBinder()->linkToDeath(this);    mClient[cameraId] = client;//串連請求後建立立的    LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());    return client;//返回CameraClient}

分以下幾個過程來分析這個函數:

a. sp client;一個CameraService內部的用戶端類

先查看當前服務端維護的camera client個數mClient[cameraId] != 0,初次啟動是該數為0.

b.擷取底層camera模組的資訊get_camera_info,查看當前的api版本資訊是CAMERA_MODULE_API_VERSION_2_0還是CAMERA_MODULE_API_VERSION_1_0.我的平台是1.0故執行如下:

    switch(deviceVersion) {      case CAMERA_DEVICE_API_VERSION_1_0:        client = new CameraClient(this, cameraClient, cameraId,                info.facing, callingPid, getpid());//client是CameraClient的基類,建立一個camerservice側的cameraclient        break;

c.CameraClient的建立,該類繼承了public CameraService::Client這個CameraService的內部類,Client繼承了BnCamera。

d.client->initialize(mModule)的處理,和硬體相關

status_t CameraClient::initialize(camera_module_t *module) {//一個cameraClient建立一個CameraHardwareInterface硬介面    int callingPid = getCallingPid();    LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);    char camera_device_name[10];    status_t res;    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);    mHardware = new CameraHardwareInterface(camera_device_name);//建立一個camera硬體介面,camera_device_name為裝置名稱    res = mHardware->initialize(&module->common);//直接底層硬體的初始    if (res != OK) {        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",                __FUNCTION__, mCameraId, strerror(-res), res);        mHardware.clear();        return NO_INIT;    }    mHardware->setCallbacks(notifyCallback,            dataCallback,            dataCallbackTimestamp,            (void *)mCameraId);//將camerservice處的回呼函數註冊到HAL處    // Enable zoom, error, focus, and metadata messages by default    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE |                  CAMERA_MSG_CONTINUOUSSNAP | CAMERA_MSG_SNAP | CAMERA_MSG_SNAP_THUMB |                  CAMERA_MSG_SNAP_FD); //enable the continuoussnap and singlesnap message by fuqiang    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);    return OK;}

這裡出現了一個封裝Camera底層操作的一個硬體介面類CameraHardwareInterface,可以屏蔽不同的平台硬體特性,主要是實現的HAL的相關操作。

step6.CameraHardwareInterface介面類的實現initialize()函數。

    status_t initialize(hw_module_t *module)    {        ALOGI("Opening camera %s", mName.string());        int rc = module->methods->open(module, mName.string(),                                       (hw_device_t **)&mDevice);//這裡開啟camera硬體裝置        if (rc != OK) {            ALOGE("Could not open camera %s: %d", mName.string(), rc);            return rc;        }        initHalPreviewWindow();//初始preview的相關流opspreview_stream_ops,初始化hal的預覽視窗        return rc;    }

這裡的module就是底層的camera模組,最終完成open的操作,這裡占時不說明HAL的操作,後續會專門分享camera的HAL的實現。

step7:setCallbacks()設定回呼函數,即註冊回呼函數到HAL處

    void setCallbacks(notify_callback notify_cb,                      data_callback data_cb,                      data_callback_timestamp data_cb_timestamp,                      void* user)    {        mNotifyCb = notify_cb;        mDataCb = data_cb;        mDataCbTimestamp = data_cb_timestamp;        mCbUser = user;        ALOGV("%s(%s)", __FUNCTION__, mName.string());        if (mDevice->ops->set_callbacks) {            mDevice->ops->set_callbacks(mDevice,                                   __notify_cb,                                   __data_cb,                                   __data_cb_timestamp,                                   __get_memory,                                   this);//傳入的是__notify_cb函數        }//硬體裝置設定回調    }

分別訊息回調,資料回調,時間戳記回調,以及記憶體相關操作的回調。

step8:

mClient[cameraId] = client將建立好的cameraclient對象維護到CameraService中並返回退出connect,而最終通過Binder驅動返回到用戶端的是CameraClient的代理BpCameraClient,是一個匿名的Binder服務。

c->mCamera = cs->connect(c, cameraId);將這個服務端的cameraclient維護到本地應用端的Camera的mCamera成員中。而後續的Camera的相關操作都通過該mCamera成員和CameraService進行進一步的互動操作。

camera的一個調用架構圖:







聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.