一、简介
Camera1的API相对简单,功能也在手机中稳定。学习也是为了巩固和完善这方面的知识。
Camera1的模块一共有以下几层:
- 1、java层
- 2、java层与C/C++的交互层-jni层
- 3、camera的客户/服务端-C/C++
- 4、camera硬件抽象层HAL-C++
二、Camera的竖向结构
1.Framework:Camera.java
Camera是应用层软件直接使用的类,涵盖了启动、预览、拍摄及关闭等操作摄像头的全部接口。
位于framework/base/core/java/android/hardware
使用Camera.open(int cameraId)
获取Camera对象public static Camera open(int cameraId) {
return new Camera(cameraId);
}
public static Camera open() {
// 获取摄像头的总个数,该方法为native方法
int numberOfCameras = getNumberOfCameras();
// 获取Camera的基本信息
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
// getCameraInfo内部调用native方法_getCameraInfo获取摄像头信息
getCameraInfo(i, cameraInfo);
// 默认使用后置摄像头
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
return null;
}
- getNumberOfCameras为native方法,实现在android_hardware_Camera.cpp中
- CameraInfo是Camera定义的静态内部类,包含facing、orientation、canDisableShutterSound;
- getCameraInfo内部调用native方法_getCameraInfo获取摄像头信息;
- open()默认启动的是后置摄像头(CAMERA_FACING_BACK)。
获取Camera对象:Camera(int cameraId) {
int err = cameraInitNormal(cameraId);
if (checkInitErrors(err)) {
switch(err) {
case EACCESS:
throw new RuntimeException("Fail to connect to camera service");
case ENODEV:
throw new RuntimeException("Camera initialization failed");
default:
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}
}
Camera构造器的核心实现在cameraInitNormal中,cameraInitNormal调用cameraInitVersion,并传入参数cameraId和CAMERA_HAL_API_VERSION_NORMAL_CONNECT,后者代表HAL的版本。private int cameraInitNormal(int cameraId) {
return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}
private int cameraInitVersion(int cameraId, int halVersion) {
...
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,ActivityThread.currentOpPackageName());
}
调用本地方法native_setup(),由此进入到android_hardware_Camera.cpp中,进入jni层
2.jni:android_hardware_Camera.cpp
由上可知,native\setup()被动态注册到JNI,通过JNI调用android_hardware_Camera_native_setup()方法。
位于frameworks/base/core/jni/android_hardware_Camera.cppstatic jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
// Convert jstring to String16
const char16_t *rawClientName = reinterpret_cast<const char16_t*>(env->GetStringChars(clientPackageName, NULL));
jsize rawClientNameLen = env->GetStringLength(clientPackageName);
...
// 在此进行请求连接至CameraService服务
camera = Camera::connect(cameraId, clientName,Camera::USE_CALLING_UID);
...
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);
...
}
Camera::connect()
- clientName是通过将clientPackageName从jstring转换为String16格式得到;
- Camera::USE_CALLING_UID是定义在Camera.h中的枚举类型,其值为ICameraService::USE_CALLING_UID(同样为枚举类型,值为-1)。
native_setup()被动态注册到JNI,通过JNI调用android_hardware_Camera_native_setup()。static JNINativeMethod camMethods[] = {
...
{ "native_setup","(Ljava/lang/Object;ILjava/lang/String;)V",(void*)android_hardware_Camera_native_setup }
...
};
3.Library:Camera Client和Camera Service
Service Manager在Binder机制中既充当守护进程的角色,同时它也充当着Server角色,然而它又与一般的Server不一样。对于普通的Server来说,Client如果想要获得Server的远程接口,那么必须通过Service Manager远程接口提供的getService接口来获得,这本身就是一个使用Binder机制来进行进程间通信的过程。而对于Service Manager这个Server来说,Client如果想要获得Service Manager远程接口,却不必通过进程间通信机制来获得,因为Service Manager远程接口是一个特殊的Binder引用,它的引用句柄一定是0。
ICameraService.h、ICameraClient.h和ICamera.h三个类定义了Camera的接口和架构,ICameraService.cpp和Camera.cpp两个文件用于Camera架构的实现。
服务端:frameworks/base/services/camera/libcameraservice/ICameraService.cpp
客户端:frameworks/base/libs/camera/ICameraClient.cpp
可以从代码中找到connect
方法中的功能sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,int clientUid)
{
return CameraBase::connect(cameraId, clientPackageName, clientUid);
}
Camera类继承模板类CameraBase,Camera::connect()调用了CameraBase.cpp中的connect()方法。
CameraBase实际上又继承了IBinder的DeathRecipient内部类,DeathRecipient虚拟继承自RefBase。template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,const String16& clientPackageName,int clientUid)
{
// 获得BnCameraClient
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
status_t status = NO_ERROR;
// 获取CameraService服务
const sp<ICameraService>& cs = getCameraService();
if (cs != 0) {
//
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,c->mCamera);
}
if (status == OK && c->mCamera != 0) {
IInterface::asBinder(c->mCamera)->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
c.clear();
}
return c;
}
template <typename TCam, typename TCamTraits>
const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
{
Mutex::Autolock _l(gLock);
if (gCameraService.get() == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16(kCameraServiceName));
if (binder != 0) {
break;
}
ALOGW("CameraService not published, waiting...");
usleep(kCameraServicePollDelay);
} while(true);
if (gDeathNotifier == NULL) {
gDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(gDeathNotifier);
gCameraService = interface_cast<ICameraService>(binder);
}
ALOGE_IF(gCameraService == 0, "no CameraService!?");
return gCameraService;
}
new TCam(cameraId)
获取BnCameraClient对象,位于ICameraClient.h文件中,继承自BnInterface类getService(String16(kCameraServiceName))
获得CameraService服务代理BpCameraService,继承自BpInterface
此处终于获得CameraService实例了,该CameraService实例是通过binder获取的。