Android Camera框架从整体看是一个c/s的架构,有两个进程:
一个是client进程,属于AP端用户的行为,是为应用程序进程,主要包括java代码与一些native c/c++代码;
另一个是service进程,属于服务端,是native c/c++代码,主要负责和linux kernel中的camera driver交互,搜集linux kernel中camera driver传上来的数据,并交给显示系统(surface)显示。
client进程与service进程通过IPC Binder机制通信,client端通过调用service端的接口实现各个具体的功能。(客户端进程承载用户的需求,由Binder进程间通信送往服务端实现设备的功能,服务端由回调函数和消息机制反馈数据返还给用户。)
Android中Camera的调用流程可分为以下几个层次:
1.AP
2.Framework
3.JNI
4.Camera client
5.binder
6.Camera service
7.Camera HAL
8.Camera Driver
android.hardware.Camera(在Framework中) 类的调用,实现相关接口,完成业务逻辑。
\vendor\mediatek\proprietary\packages\apps\Camera
\vendor\mediatek\proprietary\packages\apps\Camera2
mtk camera app有两套文件,分别是Camera和Camera2,Camera是针对api1来做的,同mtk android 6.0及之前的camera ap架构一致;而Camera2是针对兼容api1和api2来做的,但是实际查看修改代码时才发现,只是适配了api2的接口,但是实际使用的还是Camera api1,这应该是为之后的架构变化所做的修改。
两套代码结构都很不同。对于api2的真正使用,mtk放在了Android P上。
区分使用的那套,通过ap目录下的mk文件:
如Camera2目录中mk文件宏判断:
ifneq ($(filter 2 3, $(MTK_CAMERA_APP_VERSION)),)
Camera目录中mk文件宏判断:
ifeq ($(MTK_CAMERA_APP_VERSION), 1)
宏MTK_CAMERA_APP_VERSION定义在系统device目录中,通过project名去查找即可。
api路径:/android/frameworks/base/core/java/android/hardware/Camera.java
定义公开接口、变量、函数等api给ap层相机使用者,调用jni函数,来实现预览、参数设置、拍照、录像等功能。JAVA 代码到C++ 代码的桥梁。
Camera.CameraInfo 获取camera特性,如方向、id、摄像头数目等
Camera.Face 人脸数据的矩阵
Camera.Parameters 参数设置类
Camera.Size
Camera.Area
Camera.AutoFocusCallback 自动对焦回调
Camera.AutoFocusMoveCallback 连续对焦回调
Camera.ErrorCallback camera open或使用过程中出现的error回调
Camera.FaceDetectionListener 人脸检测回调
Camera.OnZoomChangeListener 焦距变化回调
Camera.PictureCallback 拍照数据回调
Camera.PreviewCallback 预览实时数据回调
Camera.ShutterCallback 拍照快门回调
Camera的java native调用部分(JNI):/android/frameworks/base/core/jni/android_hardware_Camera.cpp。
该文件中的register_android_hardware_Camera(JNIEnv *env) 函数会将native函数注册到虚拟机中,以供Framework层的java代码调用,通过该入口,可以获取到framework层用于创建android.hardware.Camera对象的相关数据。这些native函数通过调用libcamera_client.so中的Camera类实现具体的功能。
// Get all the required offsets in java class and register native functions
int register_android_hardware_Camera(JNIEnv *env)
{
.......
jclass clazz = FindClassOrDie(env, "android/hardware/Camera");
fields.post_event = GetStaticMethodIDOrDie(env, clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
clazz = FindClassOrDie(env, "android/graphics/Rect");
fields.rect_constructor = GetMethodIDOrDie(env, clazz, "" , "()V");
clazz = FindClassOrDie(env, "android/hardware/Camera$Face");
fields.face_constructor = GetMethodIDOrDie(env, clazz, "" , "()V");
clazz = env->FindClass("android/graphics/Point");
fields.point_constructor = env->GetMethodID(clazz, "" , "()V");
if (fields.point_constructor == NULL) {
ALOGE("Can't find android/graphics/Point()");
return -1;
}
// Register native functions
return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods));
//camMethods就是需要注册的函数,这里封装了一下。
}
Camera client层的定义位于frameworks/av/camera/Camera.cpp 这个类通过调用IPC binder代理来获取camera service的访问接口。
主要文件如下,client打包生成libcamera_client.so
Camera.cpp/Camera.h
CameraParameters.cpp/CameraParameters.h
ICamera.cpp/ICamera.h
ICameraClient.cpp/ICameraClient.h
CameraBase.cpp/CameraBase.h
ICameraService.aidl/
IPC binder代理来实现camera client和service的进程间通信。
在frameworks/av/camera目录下有三个camera binder类的定义。ICameraService是cameraservice的接口,ICamera是被打开的camera设备的接口,ICameraClient是camera设备返回给application framework层的接口。
Camera service层的定义位于frameworks/av/services/camera/libcameraservice/CameraService.cpp中。它是与camera HAL交互的实际代码。Service模块打包生成libcameraservice库文件。
CameraService 是Camera 服务,Camera 框架的中间层,用于向下连接CameraHardwareInterface 和向上连接Client部分,它通过调用实际的Camera hal硬件抽象层接口来实现相关功能。
frameworks\av\media\mediaserver\main_mediaserver.cpp中对camera service进行初始化的服务注册。
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
////////具体封装在defaultServiceManager()函数中
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
InitializeIcuOrDie();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
Main_MediaServer主函数由init.rc在启动是调用,所以在设备开机的时候Camera就会注册一个服务,用作binder通信,提供给client随时使用。
camera硬件抽象层接口实现,在camera service调用到CameraHardwareInterface.cpp/CameraHardwareInterface.h来进行连接。
具体路径:\frameworks\av\services\camera\libcameraservice\device1
hal层代码位置:vendor/mediatek/proprietary/hardware/mtkcam
这一层主要是基于Linux的设备驱动。驱动进行camera的点亮、上电、元数据处理等等。