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;
}

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