Android Camera HAL V3参数传递

本文探讨了Android 4.4.3版本中CameraHAL层与framework层间参数传递的方法,详细介绍了camera_metadata_tag的作用及其实现过程,包括如何定义和使用自动对焦(AF)、曝光补偿(AE)等关键参数。

最近一直在调试Android 4.4.3的Camera HAL层,对framework层到HAL的参数传递方法一直不明白,导致调试无从下手,今天总算是有点启发,也不知道对不对,但是要写出来给,一是给自己做个笔记,二是可能会对后来的朋友有些启发;

在调试Camera HAL的过程中发现,HAL层调用的许多framework层的很多回调函数,这点要注意,以前我一直以为都是只能framework向下调用HAL层的函数,而HAL层不能调用到framework层的函数,所以导致我在追踪代码的过程中有很多迷糊的地方;后来知道了这些豁然开朗;
              首先第一个很关键的头文件:myandroid/system/media/camera/include/system/camera_metadata_tags.h,这个头文件中有一个很关键的enum类型camera_metadata_tagcamera_metadata_tag 中很很多tag,每个tag后面的注释部分意思是你要定义一个相应类型的enum或int32[ ]类型的数据,并把数据的值注册到系统list中,以后framework和HAL就可以通过tag中的ID匹配相应的参数值;framework层和HAL层通过查找这个tag id找到buffer list中相应的惨值;

typedef enum camera_metadata_tag {
    ANDROID_COLOR_CORRECTION_MODE =                   // enum         | public
            ANDROID_COLOR_CORRECTION_START,
    ANDROID_COLOR_CORRECTION_TRANSFORM,               // rational[]   | public
    ANDROID_COLOR_CORRECTION_GAINS,                   // float[]      | public
    ANDROID_COLOR_CORRECTION_END,

    ANDROID_CONTROL_AE_ANTIBANDING_MODE =             // enum         | public
            ANDROID_CONTROL_START,
    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,         // int32        | public
    ANDROID_CONTROL_AE_LOCK,                          // enum         | public
    ANDROID_CONTROL_AE_MODE,                          // enum         | public
    ANDROID_CONTROL_AE_REGIONS,                       // int32[]      | public<span style="white-space:pre">	</span>//要定义一个public权限的int32[]数据,并把它注册到系统中;
    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,              // int32[]      | public
    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,            // enum         | public
    <span style="color:#ff0000;">ANDROID_CONTROL_AF_MODE</span>,                          // enum         | public<span style="white-space:pre">	</span>//自动对焦相关?
    ANDROID_CONTROL_AF_REGIONS,                       // int32[]      | public
    ANDROID_CONTROL_AF_TRIGGER, 
<span style="color:#3333ff;"><strong>ANDROID_CONTROL_AF_AVAILABLE_MODES</strong></span>,               // byte[]       | public<span style="white-space:pre">	</span>//AF控制相关
<span style="color:#ff0000;">ANDROID_FLASH_MODE</span>,                               // enum         | public<span style="white-space:pre">	</span>//闪光灯相关?
//.......................省略部分代码.............................<pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif;">ANDROID_BLACK_LEVEL_LOCK =                        // enum         | public</span>
ANDROID_BLACK_LEVEL_START, ANDROID_BLACK_LEVEL_END, //在枚举空间层次结构中的位置。所有供应商的扩展标签必须定义在标签 >=vendor_section_start 后} camera_metadata_tag_t;


上面那些camera_metadata_tag_t中有些enum类型,有些事int32类型,他们具体指什么呢?在myandroid/hardware/imx/mx6/libcamera2/MetadaManager.cpp文件中MetadaManager::createStaticInfo(camera_metadata_t **info, bool sizeRequest)函数中;

status_t MetadaManager::createStaticInfo(camera_metadata_t **info, bool sizeRequest)
{
//.......................................
static const uint8_t <span style="color:#ff0000;">availableAfModes</span>[] = {
			ANDROID_CONTROL_AF_MODE_OFF ,				// new add 
            ANDROID_CONTROL_AF_MODE_AUTO,				// new add
            ANDROID_CONTROL_AF_MODE_MACRO,				// new add 
            //ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,	// new add 
            //ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE	// new add
    };
	//添加对自动对焦模式的支持
    ADD_OR_SIZE(<span style="color:#3333ff;"><strong>ANDROID_CONTROL_AF_AVAILABLE_MODES</strong></span>,
                <span style="color:#ff0000;">availableAfModes</span>, sizeof(<span style="color:#ff0000;">availableAfModes</span>));
//.......................................
}
Camera HAL层是怎么获得Framework层传下来的参数呢?通过调用myandroid/system/media/camera/src/camera_metadata.c文件中的ANDROID_API接口find_camera_metadata_entry();find_camera_metadata_entry()函数的entry参数是输出指针,得到entry值;entry是一个camera_metadata_entry结构体;通过camera_metadata_entry的union指针传递参数值;

typedef struct camera_metadata_entry {
    size_t   index;
    uint32_t tag;
    uint8_t  type;
    size_t   count;
    union {
        uint8_t *u8;			//trigger
        int32_t *i32;			//trigger_id
        float   *f;
        int64_t *i64;			//timestamp
        double  *d;
        camera_metadata_rational_t *r;		//帧率相关
    } data;
} camera_metadata_entry_t;


myandroid/hardware/imx/mx6/libcamera2/MetadaManager.cpp

status_t MetadaManager::getFrameRate(int *value)
{
	
    camera_metadata_entry_t <span style="color:#ff0000;"><strong>streams</strong></span>;
    int res = <span style="color:#3333ff;"><strong>find_camera_metadata_entry</strong></span>(mCurrentRequest,
            ANDROID_CONTROL_AE_TARGET_FPS_RANGE, &<span style="color:#ff0000;"><strong>streams</strong></span>);
    if (res != NO_ERROR) {
        ALOGE("%s: error reading fps range tag", __FUNCTION__);
        return BAD_VALUE;
    }

    int v[2];
    for (uint32_t i = 0; i < streams.count && i < 2; i++) {
        v[i] = <strong><span style="color:#ff0000;">streams</span></strong>.data.i32[i];<span style="white-space:pre">			</span>//得到framework层的值;
    }

    if (v[0] > 15 && v[1] > 15) {
        *value = 30;
    }
    else {
        *value = 15;
    }
    return NO_ERROR;
}
framework层是怎么得到HAL层返回的值呢?

myandroid/frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
//.............................................
// Check that there's a timestamp in the result metadata
<span style="white-space:pre">	</span><strong><span style="color:#ff0000;">CameraMetadata </span></strong><span style="color:#3366ff;"><strong>captureResult</strong></span>;<span style="white-space:pre">		</span>//<span style="color: rgb(255, 0, 0); font-weight: bold; font-family: Arial, Helvetica, sans-serif;">CameraMetadata.find(tag)返回</span><span style="color: rgb(51, 102, 255); font-weight: bold; font-family: Arial, Helvetica, sans-serif;">camera_metadata_entry 就得到了HAL层传上来的参数;</span><span style="color: rgb(255, 0, 0); font-weight: bold; font-family: Arial, Helvetica, sans-serif;">
</span>        <strong><span style="color:#3366ff;">camera_metadata_entry </span></strong>entry =
                <span style="color:#3333ff;"><strong>captureResult</strong></span>.find(<span style="color:#ff0000;">ANDROID_SENSOR_TIMESTAMP</span>);
        if (entry.count == 0) {
            SET_ERR("No timestamp provided by HAL for frame %d!",
                    frameNumber);
            gotResult = false;
        } else if (timestamp != entry.data.i64[0]) {
            SET_ERR("Timestamp mismatch between shutter notify and result"
                    " metadata for frame %d (%lld vs %lld respectively)",
                    frameNumber, timestamp, entry.data.i64[0]);
            gotResult = false;
        }
//.............................................
}
其实myandroid/frameworks/av/include/camera/CameraMetadata.h是framework和HAL参数的中间class;类似个中间变量;以上内容全是个人理解,有错的地方还希望大家指正;一起进步;








<think>我们讨论的是Android Camera启动流程,从Launcher点击图标到HAL层的调用过程。这是一个涉及多个Android系统层次的问题。 在Android系统中,应用通过调用Camera API来使用相机功能。当用户点击相机图标时,Launcher会启动相机应用(通常是预装的Camera应用),然后相机应用会通过Android框架层提供的API打开相机设备,最终这些调用会通过HAL层到达具体的硬件。 整个流程大致如下: 1. 用户点击Launcher中的相机应用图标。 2. Launcher通过Intent启动相机应用(一个Activity)。 3. 相机应用在Activity启动过程中(例如onCreate或onResume中)调用CameraManager的openCamera方法来获取相机设备。 4. CameraManager会通过Binder调用CameraService(运行在system_server进程)来打开相机。 5. CameraService会通过HAL接口与底层的相机硬件进行交互。 下面我们详细描述从应用层到HAL层的调用链: 步骤1:应用层调用CameraManager.openCamera() 在相机应用中,我们通常会这样打开相机: CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); manager.openCamera(cameraId, new CameraDevice.StateCallback() { ... }, handler); 步骤2:CameraManager通过Binder调用CameraService CameraManager的openCamera方法最终会通过ICameraService.aidl定义的接口调用到CameraService的connectDevice方法(具体实现中,会通过一个Binder代理对象调用到system_server进程中的CameraService)。 步骤3CameraService处理连接请求 在CameraService中,会创建一个CameraDeviceClient对象(继承自CameraDeviceClientBase,而CameraDeviceClientBase又实现了CameraDeviceBase)来代表一个连接到相机的客户端。然后CameraService会通过调用HAL层接口来打开相机设备。 步骤4:通过HAL层打开相机 CameraService会调用到CameraProviderManager(管理相机HAL的服务)来打开相机设备。具体是通过HIDL(或AIDL,取决于Android版本)接口调用到相机HAL实现。在HAL层,会执行具体的硬件操作,比如打开摄像头设备,初始化等。 步骤5:HAL层操作硬件 HAL层的实现是由设备厂商提供的,它会根据Android定义的接口(例如ICameraProvider)实现具体的功能。在打开相机设备时,HAL层会与内核层的摄像头驱动进行交互,通过V4L2(Video for Linux 2)等框架操作硬件。 代码示例(简化流程): 由于整个流程涉及多个层次,我们不可能在一个代码片段中展示所有步骤。但我们可以展示从应用层到CameraService的调用,以及HAL层的接口定义。 应用层代码(Java)示例: 在相机应用的Activity中,打开相机的代码可能如下: ```java public class CameraActivity extends Activity { private CameraManager cameraManager; private String cameraId; private CameraDevice cameraDevice; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { // 获取第一个后置摄像头ID for (String id : cameraManager.getCameraIdList()) { CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id); Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) { cameraId = id; break; } } // 打开相机 cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { cameraDevice = camera; // 创建会话等后续操作 } @Override public void onDisconnected(CameraDevice camera) { // 处理断开 } @Override public void onError(CameraDevice camera, int error) { // 处理错误 } }, null); } catch (CameraAccessException e) { e.printStackTrace(); } } } ``` 框架层(CameraService)和HAL层的代码是C++代码,这里我们简单展示HAL层的接口定义(以HIDL为例): HAL层接口定义(ICameraProvider.hal): 在Android HAL中,相机HAL实现了ICameraProvider接口。当CameraService需要打开相机设备时,会调用ICameraProvider::getCameraDeviceInterface_V3_x()(或类似版本)来获取一个ICameraDevice实例,然后通过该实例与设备交互。 由于HAL层代码是厂商实现的,我们无法给出具体实现,但可以给出调用流程的伪代码: 在CameraService中(C++): ```cpp // 伪代码,简化流程 status_t CameraService::connectDevice(...) { // 通过CameraProviderManager获取CameraProvider sp<hardware::camera::device::V3_2::ICameraDevice> device; status_t res = CameraProviderManager::openSession(cameraId, this, &device); // 然后创建一个CameraDeviceClient对象,将device传递给它 ... } ``` 在HAL层(ICameraDevice的实现)中,厂商需要实现open方法,该方法会调用到内核驱动打开设备。 总结: 从Launcher点击图标到HAL层,整个流程是通过应用启动、框架层Binder调用、HAL层HIDL调用等步骤完成的。其中,应用层通过CameraManager发起请求,CameraService在系统进程中处理请求,并通过HAL接口调用到厂商实现的相机驱动操作。 注意:不同Android版本(尤其是Android 8.0之后)的相机架构有所变化,使用了HIDL(或更新的AIDL)来替代传统的HAL模块加载方式,但整体流程相似。 §§相关问题§§: 1. Android Camera API2中,CameraManager、CameraDevice、CameraCaptureSession之间的关系是怎样的? 2. 在Android相机HAL层中,如何实现一帧图像数据从硬件到应用层的传递? 3. 请解释Android Camera HAL3的基本架构和特性。 4. 如何编写一个自定义的Camera应用,实现基本的拍照功能?</think>### Android Camera启动流程:从Launcher到HAL层 当您在Android桌面上点击相机图标时,系统会经历以下流程将指令传递到HAL层: #### 整体流程概览 ```mermaid graph TD A[Launcher点击图标] --> B[启动Camera App] B --> C[App调用CameraManager API] C --> D[CameraService Binder调用] D --> E[CamerProvider HAL服务] E --> F[厂商HAL实现] F --> G[内核驱动] ``` #### 详细步骤分析 1. **Launcher启动相机应用** - Launcher通过`startActivity()`发送`Intent`启动相机应用 - 示例代码: ```java // Launcher内部实现简化 Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); startActivity(cameraIntent); ``` 2. **相机应用初始化** - 相机Activity在`onCreate()`/`onResume()`中调用Camera API - 关键代码: ```java // 在CameraActivity中 CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { // 相机设备就绪 } }, null); ``` 3. **框架层Binder通信** - `CameraManager`通过Binder IPC调用`CameraService`: ```cpp // frameworks/av/services/camera/libcameraservice/CameraService.cpp status_t CameraService::connect( const sp<hardware::camera2::ICameraDeviceCallbacks>& callbacks, const String16& cameraId, /* ... */) { // 验证权限和状态 // 创建CameraDeviceClient } ``` 4. **HAL层调用流程** - CameraService通过HIDL/AIDL调用CameraProvider: ```cpp // hardware/interfaces/camera/provider/2.4/ICameraProvider.hal interface ICameraProvider { getCameraDeviceInterface_V3_x(string cameraDeviceName) generates (ICameraDevice device); }; ``` 5. **厂商HAL实现** - 厂商实现的HAL层代码示例: ```cpp // vendor/implementation/CameraDevice.cpp Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback) { // 1. 初始化硬件参数 mCamera = new VendorCamera(); // 2. 打开底层设备驱动 mCamera->open("/dev/video0"); // 3. 返回设备句柄 _hidl_cb(Status::OK, this); return Void(); } ``` 6. **内核交互** - HAL层通过V4L2驱动操作摄像头: ```c // 内核驱动交互示例 int fd = open("/dev/video0", O_RDWR); struct v4l2_capability cap; ioctl(fd, VIDIOC_QUERYCAP, &cap); ``` #### 关键组件说明 1. **CameraManager** (Java) - 应用层API入口 - 通过`getSystemService()`获取实例 2. **CameraService** (C++) - 系统服务,管理所有相机设备 - 实现`ICameraService.aidl`接口 3. **CameraProvider** (HIDL/AIDL) - 标准化HAL接口 - 厂商实现具体功能 4. **厂商HAL** (C/C++) - 硬件适配层 - 实现`ICameraDevice.hal`接口 - 直接操作`/dev/videoX`设备节点 #### 权限验证流程 ```mermaid sequenceDiagram App->>+CameraService: openCamera() CameraService->>+PermissionChecker: checkCameraPermission() PermissionChecker-->>-CameraService: PERMISSION_GRANTED CameraService->>+HAL: ICameraDevice::open() HAL-->>-CameraService: SUCCESS CameraService-->>-App: CameraDevice ``` #### 性能优化点 1. **延迟优化**:异步打开相机避免UI阻塞 2. **权限缓存**:CameraService缓存权限检查结果 3. **连接池**:复用CameraDeviceClient实例 4. **预加载**:系统启动时预初始化HAL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值