
Android 的摄像头硬件抽象层 (HAL) 将摄像头 2中更高级别的摄像头框架 API 连接到您的底层摄像头驱动程序和硬件。相机子系统包括相机管道组件的实现,而相机 HAL 提供用于实现这些组件版本的接口。
建筑学
下图和列表描述了 HAL 组件。

图 1.相机架构
- 应用框架
- 在应用程序框架级别是应用程序的代码,它使用Camera 2 API 与相机硬件进行交互。在内部,此代码调用相应的Binder接口来访问与相机交互的本机代码。
- AIDL
- 与
CameraService
关联的 binder 接口可以在frameworks/av/camera/aidl/android/hardware找到。生成的代码调用较低级别的本机代码以获取对物理相机的访问权,并返回用于在框架级别创建CameraDevice
并最终创建CameraCaptureSession
对象的数据。 - 原生框架
- 此框架位于
frameworks/av/
中,提供与CameraDevice
和CameraCaptureSession
类等效的本机。另请参阅NDK camera2 参考。 - 活页夹 IPC 接口
- IPC binder 接口有助于跨进程边界进行通信。
frameworks/av/camera/camera/aidl/android/hardware
目录中有几个摄像头绑定器类调用摄像头服务。ICameraService
是相机服务的接口;ICameraDeviceUser
是特定打开的相机设备的接口;ICameraServiceListener
和ICameraDeviceCallbacks
分别是应用程序框架的CameraService
和CameraDevice
回调。 - 相机服务
- 位于
frameworks/av/services/camera/libcameraservice/CameraService.cpp
中的摄像头服务是与 HAL 交互的实际代码。 - 哈尔
- 硬件抽象层定义了相机服务调用的标准接口,您必须实现该接口才能使相机硬件正常运行。
实施 HAL
HAL 位于相机驱动程序和更高级别的 Android 框架之间,并定义了一个您必须实现的接口,以便应用程序可以正确操作相机硬件。 Camera HAL 的HIDL接口在hardware/interfaces/camera中定义。
典型的绑定 HAL 必须实现以下 HIDL 接口:
-
ICameraProvider
:用于枚举单个设备并管理它们的状态。 -
ICameraDevice
:相机设备接口。 -
ICameraDeviceSession
:活动的相机设备会话接口。
参考 HIDL 实现适用于CameraProvider.cpp
、 CameraDevice.cpp
和CameraDeviceSession.cpp
。该实现包装了仍然使用旧版 API的旧 HAL。从 Android 8.0 开始,Camera HAL 实现必须使用 HIDL API;不支持使用旧接口。
输入验证
由于 HAL 访问的资源与摄像头服务不同,因此两者之间的边界被视为安全边界。这意味着从相机服务传递的参数被认为是不受信任和未经处理的。为了防止允许攻击者提升权限或访问他们不打算访问的数据的安全漏洞,相机 HAL 必须验证从相机服务传递到 HAL 的参数。这包括检查缓冲区长度值是否在允许范围内,并在使用参数之前以及在将参数传递给硬件或内核驱动程序之前对其进行清理。
旧版 HAL 组件
本节介绍遗留 HAL 组件的架构以及如何实现 HAL。 Android 8.0 及更高版本上的相机 HAL 实现必须改用 HIDL API,如上所述。
架构(旧版)
下图和列表描述了旧版相机 HAL 组件。

图 2.传统相机架构
- 应用框架
- 在应用程序框架级别是应用程序的代码,它使用
android.hardware.Camera
API 与相机硬件进行交互。在内部,此代码调用相应的 JNI 粘合类来访问与相机交互的本机代码。 - JNI
- 与
android.hardware.Camera
关联的 JNI 代码位于frameworks/base/core/jni/android_hardware_Camera.cpp
中。此代码调用较低级别的本机代码以获取对物理相机的访问权限,并返回用于在框架级别创建android.hardware.Camera
对象的数据。 - 原生框架
- 在
frameworks/av/camera/Camera.cpp
中定义的原生框架提供了与android.hardware.Camera
类等效的原生框架。此类调用 IPC 绑定代理以获取对相机服务的访问权限。 - 活页夹 IPC 代理
- IPC 绑定代理有助于跨进程边界进行通信。在
frameworks/av/camera
目录中存在三个调用相机服务的相机绑定器类。ICameraService
是相机服务的接口,ICamera
是特定打开的相机设备的接口,ICameraClient
是设备返回应用程序框架的接口。 - 相机服务
- 位于
frameworks/av/services/camera/libcameraservice/CameraService.cpp
中的摄像头服务是与 HAL 交互的实际代码。 - 哈尔
- 硬件抽象层定义了相机服务调用的标准接口,您必须实现该接口才能使相机硬件正常运行。
- 内核驱动程序
- 相机的驱动程序与实际的相机硬件和您的 HAL 实现进行交互。摄像头和驱动程序必须支持 YV12 和 NV21 图像格式,以支持在显示器上预览摄像头图像和录制视频。
实施 HAL(旧版)
HAL 位于相机驱动程序和更高级别的 Android 框架之间,并定义了一个您必须实现的接口,以便应用程序可以正确操作相机硬件。 HAL 接口定义在hardware/libhardware/include/hardware/camera.h
和hardware/libhardware/include/hardware/camera_common.h
头文件中。
camera_common.h
定义了camera_module
,这是一个标准结构,用于获取有关摄像头的一般信息,例如摄像头 ID 和所有摄像头共有的属性(即,无论是前置摄像头还是后置摄像头)。
camera.h
包含对应于android.hardware.Camera
的代码。此头文件声明了一个camera_device
结构,该结构又包含一个camera_device_ops
结构,其中包含指向实现 HAL 接口的函数的指针。有关开发人员可以设置的相机参数的文档,请参阅frameworks/av/include/camera/CameraParameters.h
。这些参数是使用 HAL 中的int (*set_parameters)(struct camera_device *, const char *parms)
指向的函数设置的。
有关 HAL 实现的示例,请参阅hardware/ti/omap4xxx/camera
中 Galaxy Nexus HAL 的实现。
配置共享库
设置 Android 构建系统以将 HAL 实现正确打包到共享库中,并通过创建Android.mk
文件将其复制到适当的位置:
- 创建一个
device/<company_name>/<device_name>/camera
目录以包含库的源文件。 - 创建一个
Android.mk
文件来构建共享库。确保 makefile 包含以下行:LOCAL_MODULE := camera.<device_name> LOCAL_MODULE_RELATIVE_PATH := hw
您的库必须命名为
camera.<device_name>
(自动附加.so
),以便 Android 可以正确加载该库。例如,请参阅位于hardware/ti/omap4xxx/Android.mk
中的 Galaxy Nexus 相机的 makefile。 - 通过使用设备的 makefile 复制
frameworks/native/data/etc
目录中必要的功能 XML 文件来指定您的设备具有相机功能。例如,要指定您的设备具有相机闪光灯并且可以自动对焦,请在设备的<device>/<company_name>/<device_name>/device.mk
生成文件中添加以下行:PRODUCT_COPY_FILES := \ ... PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \
有关设备 makefile 的示例,请参阅
device/samsung/tuna/device.mk
。 - 在
device/<company_name>/<device_name>/media_profiles.xml
和device/<company_name>/<device_name>/media_codecs.xml
XML 文件中声明相机的媒体编解码器、格式和分辨率功能。有关详细信息,请参阅向框架公开编解码器。 - 在设备的
device/<company_name>/<device_name>/device.mk
makefile 中添加以下行,将media_profiles.xml
和media_codecs.xml
文件复制到适当的位置:# media config xml file PRODUCT_COPY_FILES += \ <device>/<company>/<device>/media_profiles.xml:system/etc/media_profiles.xml # media codec config xml file PRODUCT_COPY_FILES += \ <device>/<company>/<device>/media_codecs.xml:system/etc/media_codecs.xml
- 要将相机应用程序包含在设备的系统映像中,请在设备的
device/<company>/<device>/device.mk
生成文件中的PRODUCT_PACKAGES
变量中指定它:PRODUCT_PACKAGES := \ Gallery2 \ ...