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