迁移到 Camera2

本页介绍了增强型视觉系统 (EVS) 与 Camera2 之间的区别。还介绍了如何设置 Camera2 实现。

打开和关闭相机

EVS

openCamera 将打开设备和配置单个数据流的操作结合在一起。

Camera2

如需使用 Camera2 打开和关闭设备,请执行以下操作:

  1. 选择以下模式之一:

  2. 如需配置流,请创建包含相关输出源的捕获会话。例如,来自具有 CameraDevice.createCaptureSession() (Java) 或 ACameraDevice_createCaptureSession() (NDK) 的 ImageReader 或 SurfaceView。

    Camera2 支持同时处理多个信息流。创建多个流,用于预览、录制和图像处理等目的。 信息流充当并行流水线,可按顺序处理来自相机的原始帧。

  3. 如需关闭相机设备,请使用 CameraDevice.close() (Java) 或 ACameraDevice_close() (NDK)。

请考虑以下代码段示例:

Java

CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
    manager.openCamera(cameraId, new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            // Camera opened, now create session
        }
        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {}
        @Override
        public void onError(@NonNull CameraDevice camera, int error) {}
    }, handler);
} catch (CameraAccessException e) {
    // Handle exception
}

NDK

ACameraManager *cameraManager = ACameraManager_create();
ACameraDevice *cameraDevice = nullptr;
camera_status_t status = ACameraManager_openCamera(
    cameraManager, cameraId, &deviceStateCallbacks, &cameraDevice);

流式传输相机数据

本部分介绍了如何流式传输相机数据。

EVS

在 EVS 上,从:

  1. 启动直播,使用 startVideoStream
  2. 停止直播,使用 stopVideoStream

Camera2

在 Camera2 上,执行以下操作:

  1. 创建适合预览的 CaptureRequest,请在 Java 中使用 CameraDevice.createCaptureRequest()TEMPLATE_PREVIEW 或在 NDK 中使用 ACameraDevice_createCaptureRequest()

  2. 提交持续流式传输请求,使用 CameraCaptureSession.setSingleRepeatingRequest (Java) 或 ACameraCaptureSession_setRepeatingRequestV2 (NDK)。

  3. 停止直播,使用 CameraCaptureSession.stopRepeating (Java) 或 ACameraCaptureSession_stopRepeating (NDK)。

缓冲区管理

  • 在 EVS 上,setMaxFramesInFlight 之前控制着缓冲区数量,这可能会在数据流中发生变化。当摄像头开始流式传输时,EVS 为每个图像帧提供了一个缓冲区 ID,该 ID 与内存中的同一硬件缓冲区地址相关联。

  • 在 Camera2 上,AImageReaderImageReader 的图片数量上限是在初始化会话时通过 AImageReader_newImageReader.newInstance 设置的。会话开始后,此设置无法动态更改。为了获取每个帧的缓冲区 ID,客户端可以维护一个将从 Image 对象获得的硬件缓冲区地址与唯一标识符相关联的映射。

暂停和恢复直播

相机参数

请考虑以下代码示例:

Java

CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.set(CaptureRequest.CONTROL_EFFECT_MODE, CaptureRequest.CONTROL_EFFECT_MODE_MONO);
// Submit this request

NDK

ACaptureRequest_setEntry_i32(captureRequest, ACAMERA_CONTROL_EFFECT_MODE, 1, &effectMode);

逻辑相机

  • EVS:对于环视等逻辑摄像头,EVS 管理器会打开所有关联的实体摄像头,启动视频流,并提供一个连贯的图像阵列。

  • Camera2:如果需要使用 Camera2 实现类似的功能,应用必须管理逻辑摄像头,这需要您执行以下操作:

    • 确定与逻辑摄像头关联的物理子摄像头。
    • 打开每个必需的实体摄像头。
    • 在每个摄像头上启动视频流。
    • 根据需要同步帧。最好在 HAL 级别处理此问题,以实现硬件级同步。

我们将为现有 EVS 客户端提供兼容性库(shim 层),以方便过渡。目的是以最少的代码更改来支持 Camera2 API。

权限

EVS

访问权限仅限于特权唯一标识符 (UID)。例如,AID_AUTOMOTIVE_EVS。已弃用的权限包括 android.car.permission.USE_CAR_EVS_CAMERA

Camera2

Camera2 需要 android.permission.CAMERA。特殊情况:

安全关键型相机应用必须遵循 Design for Driving 中提供的 Google 内置预授权政策。

主要客户和次要客户

对于共享摄像头使用权限:

  • EVS 提供了显式 API setPrimaryClientforcePrimaryClient 来管理主要客户端,该客户端有权修改参数。

  • 在共享模式下打开相机时(Android 16 及更高版本),访问相机的客户端的优先级决定了主客户端。优先级最高的客户端(通常是前台应用)可以修改捕获请求参数。没有使用任何直接 API 来强制设置主状态。主状态由框架管理。

系统相机

如需限制仅允许系统或第一方应用访问某个相机设备,请在相应设备的相机 HAL 中声明 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA 功能。除了 android.permission.CAMERA 之外,客户端还必须具有 android.permission.SYSTEM_CAMERA 才能连接到此摄像头设备。

CarEVSManager 和 CarEVSService

对于 API 访问,Java 应用应使用标准 android.hardware.camera2.CameraManager 而不是 CarEVSManager

对于后视摄像头,CarEVSService 中用于监控 GEAR_SELECTION VHAL 属性并启动 activity 的逻辑必须迁移到 OEM 拥有的应用。此应用:

  • 监控 GEAR_SELECTION VHAL 属性。
  • 在挂入倒车档时启动后视摄像头 activity。
  • 使用 Camera2 API 显示摄像头画面。

为了确保后视摄像头能够以一致且不受阻碍的方式显示画面,尤其是在用户切换时或当其他应用可能会遮挡预览画面时,我们建议在通过 Camera2 实现后视摄像头功能时遵循以下准则:

显示渲染

EVS 显示屏和车载显示屏服务。

这些已弃用。

Camera2

使用标准 Android 渲染方法(包括 Surface、android.hardware.display.DisplayManagerandroid.view.Display)。

对于需要提前显示摄像头的场景,Camera2 ImageReader 可以直接访问硬件缓冲区,以便您将其与现有的基于 DRM 的显示实现集成以进行渲染。

这种提前访问摄像头仅允许具有 AID_AUTOMOTIVE_EVS_UID 的特权客户端进行,并且仅限于位于车辆外部的系统摄像头。

模拟器 HAL(EVS 模拟 HAL)

我们计划弃用 EVS 模拟 HAL。相反,原始设备制造商 (OEM) 应使用 Camera2 模拟相机 HAL hardware/google/camera/devices/EmulatedCamera/,该 HAL 将得到增强,以支持:

  • 可配置的摄像头数量。
  • 彩条测试图案。
  • 视频文件模拟。

如需在 build 中包含此 HAL,请执行以下操作:

# In device.mk
PRODUCT_SOONG_NAMESPACES += hardware/google/camera/devices/EmulatedCamera
PRODUCT_PACKAGES += com.google.emulated.camera.provider.hal

此外,还需要适当的安全增强型 Linux (SELinux) 政策,以允许 cameraserver 与模拟相机 HAL 服务进行交互。

V4L2 UVC 相机 HAL

我们计划弃用 EVS V4L2 HAL。使用 Camera2 外部相机支持功能来支持 USB 相机 (UVC)。如需了解详情,请参阅外部 USB 相机

提前访问摄像头

EVS 相机访问权限仅限于具有 AID_AUTOMOTIVE_EVS UID 的特权客户端。在 Android 启动过程完成之前访问摄像头,前提是 UID 保持为 AID_AUTOMOTIVE_EVS。不过,提前访问摄像头仅限于位于车身外部的系统摄像头。

超声波 API

我们计划弃用 EVS 超声波 API。请改用 Android 15 中引入的以下 VHAL 属性进行超声波传感器检测。

属性 类型 定义
ULTRASONICS_SENSOR_POSITION 静态 {<x>, <y>, <z>}

以毫米为单位,每个值表示传感器沿相关轴相对于 AAOS 传感器坐标系的位置。

ULTRASONICS_SENSOR_ORIENTATION 静态 {<qw>, <qx>, <qy>, <qz>}

这是传感器相对于 AAOS 传感器坐标系的四元数旋转: $$w+xi+yj+zk$$

ULTRASONICS_SENSOR_FIELD_OF_VIEW 静态 {<horizontal>, <vertical>}

传感器的水平和垂直视野范围(以度为单位)。

ULTRASONICS_SENSOR_DETECTION_RANGE 静态 {<minimum>, <maximum>}

传感器的检测范围(以毫米为单位)。

ULTRASONICS_SENSOR_DETECTION_RANGES 静态 {<range_min_1>, <range_max_1>, <range_min_2>, <range_max_2>}

以毫米为单位(含),表示传感器支持的检测范围的数组。

ULTRASONICS_SENSOR_DETECTION_RANGES 连续 {<distance>, <distance_error>}

以毫米为单位的传感器测量距离和距离误差。如果仅支持某个范围,则这是检测到的范围内的最小距离。