카메라

Android 카메라 HAL 아이콘

Android의 카메라 하드웨어 추상화 계층(HAL)은 카메라 2의 상위 수준 카메라 프레임워크 API를 기본 카메라 드라이버 및 하드웨어에 연결합니다. 카메라 하위 시스템에는 카메라 파이프라인 구성요소의 구현이 포함되어 있으며 카메라 HAL에서는 이러한 구성요소의 버전 구현에 사용할 인터페이스를 제공합니다.

아키텍처

다음 그림과 목록은 HAL 구성요소를 설명합니다.

Android 카메라 아키텍처

그림 1. 카메라 아키텍처

앱 프레임워크
앱 프레임워크 수준에는 카메라 2 API를 사용하여 카메라 하드웨어와 상호작용하는 앱의 코드가 있습니다. 내부적으로 이 코드는 해당 바인더 인터페이스를 호출하여 카메라와 상호작용하는 네이티브 코드에 액세스합니다.
AIDL
CameraService와 연결된 바인더 인터페이스는 frameworks/av/camera/aidl/android/hardware에서 확인할 수 있습니다. 생성된 코드는 하위 수준의 네이티브 코드를 호출하여 물리 카메라에 관한 액세스를 확보하고, CameraDevice와 최종적으로 프레임워크 수준에서 CameraCaptureSession 객체를 생성하는 데 사용되는 데이터를 반환합니다.
네이티브 프레임워크
frameworks/av/에 있는 이 프레임워크는 CameraDeviceCameraCaptureSession 클래스에 네이티브 프레임워크를 제공합니다. NDK camera2 참조도 참고하세요.
바인더 IPC 인터페이스
IPC 바인더 인터페이스는 프로세스 경계를 통한 통신을 용이하게 합니다. frameworks/av/camera/camera/aidl/android/hardware 디렉터리에는 카메라 서비스를 호출하는 여러 카메라 바인더 클래스가 있습니다. ICameraService는 카메라 서비스에 관한 인터페이스, ICameraDeviceUser는 특정 열린 카메라 기기에 관한 인터페이스, ICameraServiceListenerICameraDeviceCallbacks는 각각 애플리케이션 프레임워크에 관한 CameraServiceCameraDevice 콜백입니다.
카메라 서비스
frameworks/av/services/camera/libcameraservice/CameraService.cpp에 있는 카메라 서비스는 HAL과 상호작용하는 실제 코드입니다.
HAL
하드웨어 추상화 계층은 카메라 서비스가 호출하고, 카메라 하드웨어가 제대로 작동하도록 하기 위해 구현해야 하는 표준 인터페이스를 정의합니다.

HAL 구현

HAL은 카메라 드라이버와 상위 수준의 Android 프레임워크 사이에 있으며 앱이 카메라 하드웨어를 제대로 작동할 수 있도록 하기 위해 구현해야 하는 인터페이스를 정의합니다. 카메라 HAL의 HIDL 인터페이스는 hardware/interfaces/camera에 정의되어 있습니다.

일반적인 바인더화된 HAL은 다음 HIDL 인터페이스를 구현해야 합니다.

참조 HIDL 구현은 CameraProvider.cpp, CameraDevice.cpp, CameraDeviceSession.cpp에 사용할 수 있습니다. 구현은 여전히 기존 API를 사용하는 이전 HAL을 래핑합니다. Android 8.0부터 카메라 HAL 구현은 HIDL API를 사용해야 합니다. 기존 인터페이스의 사용은 지원되지 않습니다.

입력 검증

HAL은 카메라 서비스와 다른 리소스에 액세스할 수 있으므로 두 서비스 간의 경계가 보안 경계로 처리됩니다. 즉, 카메라 서비스에서 전달된 매개변수는 신뢰할 수 없고 정리되지 않은 것으로 간주됩니다. 공격자가 권한을 에스컬레이션하거나 액세스 권한이 없는 데이터에 액세스할 수 있게 하는 보안 취약점을 방지하려면 카메라 HAL이 카메라 서비스에서 HAL로 전달된 매개변수를 검증해야 합니다. 여기에는 버퍼 길이 값이 허용 범위 내에 있는지 확인하고 사용 전에 그리고 하드웨어나 커널 드라이버에 전달하기 전에 매개변수를 정리하는 것이 포함됩니다.

기존 HAL 구성요소

이 섹션에서는 기존 HAL 구성요소의 아키텍처와 HAL 구현 방법을 설명합니다. Android 8.0 이상에서 카메라 HAL 구현은 위에 설명된 HIDL API를 대신 사용해야 합니다.

아키텍처(기존)

다음 그림과 목록은 기존 카메라 HAL 구성요소를 설명합니다.

Android 카메라 아키텍처

그림 2. 기존 카메라 아키텍처

앱 프레임워크
앱 프레임워크 수준에는 android.hardware.Camera API를 사용하여 카메라 하드웨어와 상호작용하는 앱의 코드가 있습니다. 내부적으로 이 코드는 해당 JNI glue 클래스를 호출하여 카메라와 상호작용하는 네이티브 코드에 액세스합니다.
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 디렉터리에는 카메라 서비스를 호출하는 카메라 바인더 클래스 3개가 있습니다. ICameraService는 카메라 서비스에 관한 인터페이스, ICamera는 특정 열린 카메라 기기에 관한 인터페이스, ICameraClient는 앱 프레임워크로 돌아가는 기기의 인터페이스입니다.
카메라 서비스
frameworks/av/services/camera/libcameraservice/CameraService.cpp에 있는 카메라 서비스는 HAL과 상호작용하는 실제 코드입니다.
HAL
하드웨어 추상화 계층은 카메라 서비스가 호출하고, 카메라 하드웨어가 제대로 작동하도록 하기 위해 구현해야 하는 표준 인터페이스를 정의합니다.
커널 드라이버
카메라의 드라이버는 실제 카메라 하드웨어 및 HAL 구현과 상호작용합니다. 카메라 및 드라이버가 YV12 및 NV21 이미지 형식을 지원해야 카메라 이미지를 디스플레이에서 미리 볼 수 있고 동영상 녹화가 가능합니다.

HAL 구현(기존)

HAL은 카메라 드라이버와 상위 수준의 Android 프레임워크 사이에 있으며 앱이 카메라 하드웨어를 제대로 작동할 수 있도록 하기 위해 구현해야 하는 인터페이스를 정의합니다. HAL 인터페이스는 hardware/libhardware/include/hardware/camera.hhardware/libhardware/include/hardware/camera_common.h 헤더 파일에 정의되어 있습니다.

camera_common.h는 카메라 ID, 모든 카메라(즉, 전면 카메라와 후면 카메라 모두)의 공통 속성 등 카메라에 관한 일반 정보를 가져오는 표준 구조인 camera_module을 정의합니다.

camera.h에는 android.hardware.Camera에 해당하는 코드가 포함됩니다. 이 헤더 파일은 HAL 인터페이스를 구현하는 함수에 관한 포인터가 있는 camera_device_ops 구조체를 포함하는 camera_device 구조체를 선언합니다. 개발자가 설정할 수 있는 카메라 매개변수에 관한 문서는 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 파일을 생성하여 이를 적절한 위치에 복사합니다.

  1. 라이브러리의 소스 파일을 포함할 device/<company_name>/<device_name>/camera 디렉터리를 생성합니다.
  2. 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을 참고하세요.

  3. 기기의 makefile과 함께 frameworks/native/data/etc 디렉터리에 필요한 기능 XML 파일을 복사하여 기기에 카메라 기능이 있다고 명시합니다. 예를 들어 기기에 카메라 플래시가 있고 자동 초점을 사용할 수 있다고 명시하려면 기기의 <device>/<company_name>/<device_name>/device.mk makefile에 다음 행을 추가합니다.
    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를 참고하세요.

  4. 카메라의 미디어 코덱, 형식 및 해상도 기능을 device/<company_name>/<device_name>/media_profiles.xmldevice/<company_name>/<device_name>/media_codecs.xml XML 파일에 선언합니다. 자세한 내용은 프레임워크에 코덱 노출을 참고하세요.
  5. 기기의 device/<company_name>/<device_name>/device.mk makefile에 다음 행을 추가하여 media_profiles.xmlmedia_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
    
  6. 기기의 시스템 이미지에 카메라 앱을 포함하려면 기기의 device/<company>/<device>/device.mk makefile에 있는 PRODUCT_PACKAGES 변수에 이를 명시합니다.
    PRODUCT_PACKAGES := \
    Gallery2 \
    ...