Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android4.2.2 CameraService服務啟動和應用端camera初始化記錄

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

編輯:關於Android編程

之前的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 service
static 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的一個調用架構圖:

\







  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved