Android框架之Camera(1)Camera服務的前世今生


Android Camera框架及Camera服務框架(右側紅框)

1、感知Camera服務

Android中Camera服務名稱爲“media.camera”,通過service命令可以查看服務的包名:

# service list |grep media.camera
73	media.camera: [android.hardware.ICameraService]
如果要查看系統中Camera的硬件等信息,就得藉助dumpsys命令了:
# dumpsys media.camera
Camera module HAL API version: 0x0
Camera module API version: 0x22
Camera module name: RICH_ICS_CameraHal
Camera module author: rich
Number of camera devices: 2

Camera 0 static information:
  Facing: BACK
  Orientation: 0
  Device version: 0x100
  Device is closed, no client instance
Camera 1 static information:
  Facing: FRONT
  Orientation: 0
  Device version: 0x100
  Device is open. Client instance dump:
Client[1] (0xb776c0e0) PID: 2479

Camera traces (0):
  No camera traces collected.
上述顯示了Camera的HAL層模塊信息、內置前後兩個攝像頭、當前開啓了前置攝像頭及開機攝像頭進程的PID等等。當然,我們可以修改這部分的實現來提供更多的信息打印。

:系統的絕大部分信息,比如內存、GPU、Activity等等都可以通過dumpsys命令dump出來,所以dumpsys是一個調試利器。但是不要以爲dumpsys功能多麼強大,它的全部代碼包括註釋、頭文件引用在內總共不超過100行,也就是說,dumpsys僅僅是一個入口,通過Binder這個橋板調用模塊的服務,由具體的服務dump相應的信息。參見dumpsys源碼frameworks/native/cmds/dumpsys/dumpsys.cpp。


2、Camera服務的註冊

“media.camera”是一個純C/C++服務,所以它是通過寫到init.rc腳本文件、由腳本解析進程啓動的:

service media /system/bin/mediaserver
	class main
	user media
	group system audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
	ioprio rt 4

二進制mediaserver文件對應的實現文件爲main_mediaserver.cpp,它裏面啓動了很多media相關的服務,其中就有Camera服務

frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc, char** argv)
{
    signal(SIGPIPE, SIG_IGN);
    if (doLog && (childPid = fork()) != 0) {
    } else {
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();

        AudioFlinger::instantiate();
        MediaPlayerService::instantiate();
        CameraService::instantiate();
        AudioPolicyService::instantiate();

        registerExtensions();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }
}

閒扯信號:在進程運行過程中,kernel會把某些事件(events)上報給進程,進程通過註冊不同的handler處理這些信號;如果進程沒有主動處理,某些信號的默認動作是終結進程,表現出來就是程序掛掉。對於4行的SIGPIPE信號,這裏的處理方式就是忽略(避免程序掛掉)。kernel發SIGPIPE信號的場景:我們寫一個pipeline,該pipeline的讀端closed或terminated了。最常見的就是通過socket發送數據,但socket已經disconnected。

扯回來,這裏註冊Camera服務的就是12行CameraService::instantiate()。來看CameraService類的定義(截取部分):

CameraService.h (frameworks\av\services\camera\libcameraservice)
class CameraService :
    public BinderService<CameraService>,
    public BnCameraService,
    public IBinder::DeathRecipient,
    public camera_module_callbacks_t
{
    friend class BinderService<CameraService>;
public:
    // Implementation of BinderService<T>
    static char const* getServiceName() { return "media.camera"; }

                        CameraService();
    virtual             ~CameraService();

    virtual status_t    dump(int fd, const Vector<String16>& args);
}
dumpsys那些信息的打印就是16行dump函數負責實現的。instantiate()來自CameraService的父類BinderService,BinderService是一個模版類:

template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }

    static void instantiate() { publish(); }

};
CameraService替換模版之後:

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(); }
};
這樣,通過IServiceManager#addService()服務“media.camera”就被添加到了系統中。

3、Camera服務的使用

CameraManager類獲取“media.camera”服務,通過它和攝像頭打交道:

CameraManager.java (frameworks\base\core\java\android\hardware\camera2)
public final class CameraManager {
    /**
     * This should match the ICameraService definition
     */
    private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";

    private final ICameraService mCameraService;
    public CameraManager(Context context) {
        mContext = context;

        IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
        ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);

        /**
         * Wrap the camera service in a decorator which automatically translates return codes
         * into exceptions, and RemoteExceptions into other exceptions.
         */
        mCameraService = CameraBinderDecorator.newInstance(cameraServiceRaw);
    }
}

這樣,右側紅框中的Camera服務框架流程就走完了。


以上是Java代碼使用Camera服務的示例,純C/C++使用的例程如下:

using namespace android;

int main(int argc, char* const argv[])
{
    signal(SIGPIPE, SIG_IGN);
    sp<IServiceManager> sm;
    sp<IBinder> binder;
    sp<ICameraService> cameraService;
    fflush(stdout);

    sm = defaultServiceManager();
    if (sm == NULL) {}

	binder = sm->getService(String16("media.camera"));
    if (binder == NULL) {}

    cameraService = ICameraService::asInterface(binder); // libcamera_client

    int cam_num = cameraService->getNumberOfCameras();
    printf("System has %d cameras\n", cam_num);

    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章