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