Android Camera 流程学习记录(二)—— Camera Open 调用流程

这篇博客详细记录了Android Camera打开流程,从Camera.java的open方法开始,逐层深入到Framework、Android Runtime、C/C++ Libraries以及HAL层。通过源码分析,解释了如何从Java层调用到Native层,最终到达硬件接口,揭示了Android Camera服务的内部工作机制。
摘要由CSDN通过智能技术生成


简介

  • 这一章里,我们将 Camera.java 中的 open() 方法作为切入点。作为打开摄像头的方法,无论哪种 Camera 应用都需要调用到它。
  • Camera.open() 被调用开始,这一指令是如何通过 Framework 层走到 C/C++ 层,又是如何进入 HAL 层从而使得指令能够到达设备端。
  • 通过追踪源码,我们可以比较清晰地了解整个过程。
  • 接下来按照 Framework -> Android Runtime -> C/C++ Libraries -> HAL 的顺序去分析整个调用流程。
  • NOTE:



Open flow



1. Framework


1.1 Camera.java

  • 路径:frameworks/base/core/java/android/hardware/Camera.java
  • 首先从 Open() 方法开始:
    • 获取 Camera 设备的个数。
    • 依次获取设备信息,如果是获取到后置摄像头(默认),则调用 new Camera(int) 构造对应的摄像头实例。
  • 注释翻译:
    • 构造一个新的摄像头对象,以获取第一个后置摄像头。
    • 若设备中没有后置摄像头,则返回 null
  • NOTE:还有一个方法 open(int) ,它可以直接指定打开的摄像头。
/***    
* Creates a new Camera object to access 
* the first back-facing camera on the     
* device. If the device does not have a back-facing camera,
* this returns null.     
* @see #open(int)     
*/
public static Camera open() {
    int numberOfCameras = getNumberOfCameras();        
    CameraInfo cameraInfo = new CameraInfo();
    for (int i = 0; i < numberOfCameras; i++) {
        getCameraInfo(i, cameraInfo);
        if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
            return new Camera(i);
        } 
    }        
    return null;    
}
  • Camera(int cameraId)
    • 通过调用 cameraInitNormal(Id) 方法对指定摄像头进行初始化。
/** used by Camera#open, Camera#open(int) */    
Camera(int cameraId) {        
    int err = cameraInitNormal(cameraId);        
    if (checkInitErrors(err)) {            
        if (err == -EACCES) {                
            throw new RuntimeException("Fail to connect to camera service");            
        } else if (err == -ENODEV) {                
            throw new RuntimeException("Camera initialization failed");            
        }            
    // Should never hit this.            
    throw new RuntimeException("Unknown camera error");        
    }    
}
  • cameraInitNormal(int cameraId)
    • 指定 halVersion 参数。
    • 调用 cameraInitVersion(int cameraId, int halVersion)
private int cameraInitNormal(int cameraId) {        
    return cameraInitVersion(cameraId, 
            CAMERA_HAL_API_VERSION_NORMAL_CONNECT);    
}
  • cameraInitVersion(int cameraId, int halVersion)
    • 将各个回调函数置空。
    • Looper 的作用没有仔细研究,从代码逻辑上看,可能与事件的监听(需要循环操作)有关。
    • 通过 Looper 对事件处理对象进行实例化后,就调用 native_setup 方法进入 JNI(Java Native Interface) 库中调用对应的函数。
    • 至此,open() 方法开始进入 Android Runtime 层。
private int cameraInitVersion(int cameraId,
                              int halVersion) {        
    mShutterCallback = null;        
    mRawImageCallback = null;        
    mJpegCallback = null;        
    mPreviewCallback = null;        
    mPostviewCallback = null;        
    mUsingPreviewAllocation = false;        
    mZoomListener = null;        

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

1.2 Framework 中流程简图

流程简图



2. Android Runtime


2.1 android_hardware_Camera.cpp

  • 路径:frameworks/base/core/jni/android_hardware_Camera.cpp
  • native_setup()
    • 刚开始要先把 clientPackageName 做一个类型转换,变成 clientName
    • 建立一个 Camera 类型的 StrongPointer(sp)
    • 通过函数 Camera::connect()Camera::connectLegacy(),让客户端与服务端进行连接,并返回相应的 Camera 实例。
    • 最后对返回的实例进行一些基本的检查,并保存上下文。
    • connect() 的时候,就进入了 C/C++ Libraries 的 C/S 结构中,而 Camera 则属于 Client
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env,
    jobject thiz, jobject weak_this,
    jint cameraId, jint halVersion,
    jstring clientPackageName)
{
    // convert jstring to String16(clientPackageName -> clientName) 
    ......
    ......

    sp<Camera> camera;
    if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
        /***** NOTE THIS *****/
        // Default path: hal version is do
  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值