Android Camera 打开预览流程分析--打开camera的SDK流程
Posted Give.Me.Five
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Camera 打开预览流程分析--打开camera的SDK流程相关的知识,希望对你有一定的参考价值。
android系统应用场景中,Camera的使用场景变得越来越重要,在手机端不管是牌照美颜,还是拍小视频上传小视频平台。在其他领域,如车载,倒车视频,360全景影像也同样会用到Camera接口。那我们这个系列就拿Camera来分析了,我们主要就是android camera流程进行一个分析,对于照片美颜,视频上传这些就不在我们关注的范围了。那我们分析还是带着问题去分析吧,Camera就如何打开的,现在一个手机上少则2,3个摄像头,多着5~6个摄像头,那如何去打开想要的那个摄像头呢。另一方面的问题就是Camera预览窗口的图像是如何传到我们打开的那个窗口的,经过了那些流程呢。我们后续的分析文章就围绕着两个方面来展开分析。
## Camera的分层框架 (等分析完这两个流程,应该就可以画出这个框图了)
HAL层服务:frameworks/hardware/interfaces/cameraservice
FW层服务: frameworks/av/services/camera/libcameraservice
FW层SDK: frameworks/base/core/java/android/hardware/camera(2)
Camera的打开
我们就从android 标准的camera open接口开始撸:
open() ------framework/base/core/java/android/hardware/camera.java
new Camera(int id)
cameraInitVersion(int cameraId, int halVersion)
native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName)
android_hardware_Camera_native_setup(..., jint cameraId, jint halVersion, jstring clientPackageName) -----framework/base/core/jni/android_hardware_camera.cpp
Camera从open接口开始分析,直接就调用到JNI中去了,我们接着从JNI中继续分析:
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
...
//调用camera的connect接口 打开camera
camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
...
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);
// save context in opaque field
env->SetLongField(thiz, fields.context, (jlong)context.get());
// Update default display orientation in case the sensor is reverse-landscape
CameraInfo cameraInfo;
//获取camera的信息
status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
...
从JNI的native_setup中可以看到,调用了camera的connect接口,成功打开之后就可以获取camera的信息了. 再往下分析时,发现很多不对劲的地方,网上去百度了下,发现我们现在分析的camera 接口是Camera 最早的接口了,现在基本被弃用了,现在基本都是是使用Camera2的API接口,Camera2 与Camera 接口还是有挺大区别。Camera接口都被弃用了,我们就直接上手分析Camera2的接口吧。
Camera2 的接口
上面有说到camera 已经被弃用了,都推荐使用camera2的接口。我们就直接再从camera2 开始分析。camer2中有好些类:
CameraManager
相机系统服务,用于管理和连接相机设备
CameraDevice
相机设备类,和Camear1中的Camera类似
CameraCharacteristics
用于获取相机信息,内部携带大量的相机信息,包括摄像头的正反等,和Camear1中的Camera.Parameters同等功能。
CameraRequest
相机捕获图像的设置请求,包括sensor, flashlight等
CameraCaptureSession
请求抓去相机图像帧的会话,会话会创建一个通道,一个CameraDevice只能打开一个CameraCaptureSession.源头是Target, Target可以是Preview, 也可以是ImageReader
打开相机
public void Open(){
CameraManager cameraManager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
for(String cameraId: cameraManager.getCameraIdList()){
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
//打开相机,第一个参数:哪个摄像头,第二个参数mStateCallback为相机打开的回调接口,第三个参数用来确定callback在哪个线程中执行,为null的话,在当前线程中执行
cameraManager.openCamera(cameraId, mStateCallback, null)
}
}
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback(){
public void onOpened(CameraDevice camera){
mCameraDevice = camera;
...
}
public void onDisconnected(CameraDevice camera){
camera.close();
mCameraDevice = null;
}
public void onError(){CameraDevice camera, int error}{
camera.close();
mCameraDevice = null;
}
}
打开Camera时将CameraDevice.StateCallback对象传给openCamera当做参数,在OnOpened的回调中,再把Camera对象传给mCameraDevice, 后面就是用mCameraDevice 来操作。
那我们看看CameraManager.openCamera的流程吧。
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
USE_CALLING_UID);
}
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid)
throws CameraAccessException {
......
openCameraDeviceUserAsync(cameraId, callback, executor, clientUid);
}
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Executor executor, final int uid)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
//初始化android.hardware.camera2.impl.CameraDeviceImpl
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
executor,
characteristics,
mContext.getApplicationInfo().targetSdkVersion);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
//初始化CameraService
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
//CameraService 连接设备
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid);
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
这一步调用就直接调用到CameraService 里去了,与其他服务不同的是,其他服务直接是在SystemServer里的一个服务,CameraService是运行在CameraServer的一个独立进程中的。里面是使用cpp代码写的一个进程。下篇我们继续研究这个CameraService进程。
以上是关于Android Camera 打开预览流程分析--打开camera的SDK流程的主要内容,如果未能解决你的问题,请参考以下文章
Android Camera 打开预览流程分析--CameraService中的打开流程
Android Camera 打开预览流程分析--打开camera的SDK流程
Android Camera 打开预览流程分析--打开camera的SDK流程
Android Camera 打开预览流程分析--打开camera的SDK流程