센서 다중 HAL

센서 다중 HAL은 센서 HAL이 다른 센서 HAL과 함께 실행될 수 있도록 하는 프레임워크입니다. 센서 다중 HAL은 공급업체 파티션에 동적 라이브러리로 저장된 센서 하위 HAL을 동적으로 로드한 다음, 이 하위 HAL에 이벤트 게시 처리와 wake lock 획득 및 해제 처리가 가능한 콜백 객체를 제공합니다. 센서 하위 HAL은 공급업체 파티션의 공유 객체에 빌드된 센서 HAL로, 다중 HAL 프레임워크에 의해 사용됩니다. 이러한 하위 HAL은 서로 종속되지 않으며, 프로세스의 기본 함수가 포함된 다중 HAL 코드에도 종속되지 않습니다.

Android 11 또는 이후 버전을 실행하는 기기에서 사용할 수 있는 센서 다중 HAL 2.1은 힌지 각 센서 유형을 노출할 수 있는 하위 HAL의 로드를 지원하는 센서 다중 HAL 2.0의 반복입니다. 이 센서 유형을 지원하려면 하위 HAL이 2.1 SubHal 헤더에 정의된 하위 HAL API를 사용해야 합니다.

센서 AIDL HAL을 사용하는 Android 13 이상을 실행하는 기기의 경우 다중 HAL shim 레이어를 사용하여 다중 HAL 기능을 허용할 수 있습니다. 구현 세부정보는 센서 AIDL HAL과 함께 센서 다중 HAL 사용을 참고하세요.

센서 다중 HAL 2와 센서 HAL 2의 차이점

Android 10 또는 이후 버전을 실행하는 기기에서 사용할 수 있는 센서 다중 HAL 2에는 HAL API와의 상호작용을 보다 용이하게 하기 위해 센서 HAL 2 상단에 몇 가지 추상화가 도입되었습니다. 또한 센서 다중 HAL 2에는 HalProxy가 하위 HAL과 상호작용할 수 있도록, 센서 HAL 2 인터페이스와 V2_1/SubHal(또는 V2_0/SubHal) 인터페이스의 구현을 처리하는 HalProxy 클래스가 도입되었습니다.

ISensorsSubHal 인터페이스는 다음 측면에서 2.1/ISensors.hal(또는 2.0/ISensors.hal) 인터페이스와 다릅니다.

  • 초기화 메서드가 두 개의 FMQ와 ISensorsCallback 대신 IHalProxyCallback 클래스를 전달합니다.
  • 하위 HAL이 버그 신고에서 디버깅 정보를 제공하는 디버그 함수를 구현해야 합니다.
  • 로드된 하위 HAL이 다른 하위 HAL과 구분될 수 있도록 하위 HAL이 이름 함수를 구현해야 합니다.

센서 다중 HAL 2와 센서 HAL 2의 주요 차이점은 초기화 함수에 있습니다. IHalProxyCallback 인터페이스는 FMQ를 제공하는 대신 두 가지 메서드를 제공합니다. 하나는 센서 프레임워크에 센서 이벤트를 게시하는 메서드이고, 다른 하나는 wake lock을 만드는 메서드입니다. 내부적으로 센서 다중 HAL은 모든 하위 HAL의 센서 이벤트를 적시에 전달할 수 있도록 FMQ와의 모든 상호작용을 관리합니다. wake lock의 타임아웃 부담을 센서 다중 HAL에 위임하고 wake lock 사용을 센서 다중 HAL 전반에 공통된 하나의 wake lock에 집중시킬 때는 하위 HAL에 createScopedWakelock 메서드를 사용하는 것이 좋습니다. 그러면 호출 잠금 및 잠금 해제가 최소화됩니다.

센서 다중 HAL 2에는 안전 기능도 기본적으로 제공됩니다. 그리고 FMQ가 가득 차거나 Android 센서 프레임워크가 다시 시작되어 센서 상태를 재설정해야 하는 상황을 처리합니다. 또한 이벤트가 HalProxy 클래스에 게시되었지만 센서 프레임워크가 이벤트를 즉시 수락할 수 없는 경우 센서 다중 HAL은 이벤트를 백그라운드 스레드로 옮겨, 이벤트가 게시되기를 기다리는 동안 모든 하위 HAL에서 작업이 계속 진행되도록 합니다.

소스 코드 및 참조 구현

모든 센서 다중 HAL 코드는 hardware/interfaces/sensors/common/default/2.X/multihal/에 있습니다. 다음은 일부 리소스의 포인터입니다.

  • HalProxy.h: HalProxy 객체는 센서 다중 HAL에 의해 인스턴스화되며 하위 HAL의 데이터를 센서 프레임워크로 전달하는 작업을 처리합니다.
  • HalProxy.cpp: HalProxy의 구현에는 하위 HAL과 센서 프레임워크 간의 다중 통신에 필요한 모든 로직이 포함되어 있습니다.
  • SubHal.h: ISensorsSubHal 인터페이스는 하위 HAL이 HalProxy와 호환되려면 따라야 하는 인터페이스를 정의합니다. 하위 HAL은 postEventscreateScopedWakelockHalProxyCallback 객체를 사용할 수 있도록 초기화 메서드를 구현합니다.

    다중 HAL 2.0 구현에는 SubHal.h의 버전 2.0을 사용합니다.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: 이 단위 테스트는 HalProxy 구현을 확인합니다.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: 이 하위 HAL 구현 예시에서는 가짜 센서를 사용하여 가짜 데이터를 생성합니다. 여러 하위 HAL이 기기에서 어떻게 상호작용하는지 테스트하는 데 유용합니다.

구현

이 섹션에서는 다음 상황에서 센서 다중 HAL을 구현하는 방법을 설명합니다.

센서 AIDL HAL과 함께 센서 다중 HAL 사용

센서 AIDL HAL에서 다중 HAL 기능을 허용하려면 AIDL 다중 HAL shim 레이어 모듈(hardware/interfaces/sensors/aidl/default/multihal/에 있음)을 가져옵니다. 모듈은 AIDL 및 HIDL 센서 HAL 정의 유형 간의 변환을 처리하고 센서 다중 HAL 2.1 구현에서 설명하는 다중 HAL 인터페이스 주변의 래퍼를 정의합니다. AIDL 다중 HAL shim 레이어는 센서 다중 HAL 2.1을 구현하는 기기와 호환됩니다.

AIDL 다중 HAL shim 레이어를 사용하면 센서 AIDL HAL에서 헤드 추적기와 제한 축 IMU 센서 유형을 노출할 수 있습니다. AIDL HAL 인터페이스에서 정의한 이러한 센서 유형을 사용하려면 getSensorsList_2_1() 구현의 SensorInfo 구조체에 type 필드를 설정합니다. 이는 AIDL 및 HIDL 센서 HAL의 정수 지원 센서 유형 필드가 겹치지 않으므로 안전합니다.

센서 다중 HAL 2.1 구현

새로운 기기에 센서 다중 HAL 2.1을 구현하려면 다음 단계를 따르세요.

  1. SubHal.h에 설명된 대로 ISensorsSubHal 인터페이스를 구현합니다.
  2. SubHal.hsensorsHalGetSubHal_2_1 메서드를 구현합니다.
  3. cc_library_shared 대상을 추가하여, 새로 구현된 하위 HAL을 빌드합니다. 대상을 추가하는 경우:

    1. 기기의 공급업체 파티션 중 한 곳에 대상이 푸시되도록 합니다.
    2. /vendor/etc/sensors/hals.conf에 있는 구성 파일에서 라이브러리 경로를 새 줄에 추가합니다. 필요한 경우 hals.conf 파일을 만듭니다.

    하위 HAL 라이브러리 빌드를 위한 Android.bp 항목의 예는 hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp를 참고하세요.

  4. 기기에 지원되는 HAL 목록이 포함된 manifest.xml 파일에서 모든 android.hardware.sensors 항목을 삭제합니다.

  5. device.mk 파일에서 모든 android.hardware.sensors 서비스와 service.rc 파일을 삭제하고 PRODUCT_PACKAGESandroid.hardware.sensors@2.1-service.multihalandroid.hardware.sensors@2.1-service.multihal.rc를 추가합니다.

부팅 시 HalProxy가 시작하고, 새로 구현된 하위 HAL을 찾은 다음 찾은 하위 HAL을 sensorsHalGetSubHal_2_1을 호출하여 초기화합니다.

센서 다중 HAL 2.0에서 다중 HAL 2.1로 포팅

다중 HAL 2.0에서 다중 HAL 2.1로 포팅하려면 SubHal 인터페이스를 구현하고 하위 HAL을 다시 컴파일합니다.

2.0과 2.1 SubHal 인터페이스의 차이점은 다음과 같습니다.

  • IHalProxyCallback은 버전 2.1의 ISensors.hal 사양에서 생성된 유형을 사용합니다.
  • initialize() 함수는 2.0 SubHal 인터페이스의 IHalProxyCallback이 아닌 새로운 IHalProxyCallback을 전달합니다.
  • 하위 HAL은 getSensorsListinjectSensorData 대신에 getSensorsList_2_1injectSensorData_2_1을 구현해야 합니다. 이러한 메서드가 버전 2.1의 ISensors.hal 사양에 추가된 새로운 유형을 사용하기 때문입니다.
  • 다중 HAL이 하위 HAL을 버전 2.1의 하위 HAL로 처리하려면 하위 HAL이 sensorsHalGetSubHal이 아닌 sensorsHalGetSubHal_2_1을 노출해야 합니다.

센서 HAL 2.0에서 포팅

센서 HAL 2.0에서 센서 다중 HAL 2.0으로 업그레이드할 때는 HAL 구현이 다음 요구사항을 충족하는지 확인해야 합니다.

HAL 초기화

센서 HAL 2.0에는 센서 서비스가 FMQ와 동적 센서 콜백을 전달할 수 있는 초기화 기능이 있습니다. 센서 다중 HAL 2.0에서 initialize() 함수는 센서 이벤트 게시, wake lock 획득, 동적 센서 연결 및 연결 해제 통보에 사용해야 하는 단일 콜백을 전달합니다.

다중 HAL 구현에 센서 이벤트 게시

FMQ를 통해 센서 이벤트를 게시하는 대신 하위 HAL은 센서 이벤트가 사용 가능할 때 IHalProxyCallback에 센서 이벤트를 작성해야 합니다.

WAKE_UP 이벤트

센서 HAL 2.0에서 HAL은 자체 구현의 wake lock을 관리할 수 있습니다. 센서 다중 HAL 2.0에서 하위 HAL은 다중 HAL 구현에 wake lock을 관리하도록 허용합니다. 또한 createScopedWakelock을 호출하여 wake lock 획득을 요청할 수 있습니다. wake-up 이벤트를 다중 HAL 구현에 게시할 때 잠긴 범위의 wake lock을 획득하여 postEvents에 전달해야 합니다.

동적 센서

센서 다중 HAL 2.0에서는 동적 센서 연결이 변경될 때마다 IHalProxyCallbackonDynamicSensorsConnectedonDynamicSensorsDisconnected를 호출해야 합니다. 이러한 콜백은 initialize() 함수를 통해 제공되는 IHalProxyCallback 포인터의 일부로 사용할 수 있습니다.

센서 HAL 1.0에서 포팅

센서 HAL 1.0에서 센서 다중 HAL 2.0으로 업그레이드할 때는 HAL 구현이 다음 요구사항을 충족하는지 확인해야 합니다.

HAL 초기화

하위 HAL과 다중 HAL 구현 간의 콜백을 설정하는 데 initialize() 함수를 사용할 수 있어야 합니다.

사용할 수 있는 센서 노출

센서 다중 HAL 2.0에서 getSensorsList() 함수는 센서 HAL이 다시 시작되는 중이더라도 단일 기기 부팅 시 동일한 값을 반환해야 합니다. 그러면 시스템 서버가 다시 시작되면 프레임워크가 센서 연결을 다시 시도할 수 있습니다. getSensorsList()에서 반환된 값은 기기가 재부팅한 후에 변경 가능합니다.

다중 HAL 구현에 센서 이벤트 게시

센서 HAL 2.0에서 하위 HAL은 poll()가 호출되기를 기다리는 대신 센서 이벤트가 사용 가능할 때마다 미리 IHalProxyCallback에 센서 이벤트를 작성해야 합니다.

WAKE_UP 이벤트

센서 HAL 1.0에서 HAL은 자체 구현의 wake lock을 관리할 수 있습니다. 센서 다중 HAL 2.0에서 하위 HAL은 다중 HAL 구현에 wake lock을 관리하도록 허용합니다. 또한 createScopedWakelock을 호출하여 wake lock 획득을 요청할 수 있습니다. wake-up 이벤트를 다중 HAL 구현에 게시할 때 잠긴 범위의 wake lock을 획득하여 postEvents에 전달해야 합니다.

동적 센서

센서 HAL 1.0에서는 동적 센서가 poll() 함수를 통해 반환됩니다. 센서 다중 HAL 2.0에서는 동적 센서 연결이 변경될 때마다 IHalProxyCallbackonDynamicSensorsConnectedonDynamicSensorsDisconnected를 호출해야 합니다. 이러한 콜백은 initialize() 함수를 통해 제공되는 IHalProxyCallback 포인터의 일부로 사용할 수 있습니다.

센서 다중 HAL 1.0에서 포팅

센서 다중 HAL 1.0에서 기존 구현을 포팅하려면 다음 단계를 따르세요.

  1. 센서 HAL 구성이 /vendor/etc/sensors/hals.conf.에 있는지 확인합니다. 이때 /system/etc/sensors/hals.conf에 있는 파일을 옮기는 작업을 진행해야 할 수도 있습니다.
  2. hardware/hardware.hhardware/sensors.h 참조는 HAL 2.0에 지원되지 않으므로 삭제합니다.
  3. 센서 Hal 1.0에서 포팅에 설명된 대로 하위 HAL을 포팅합니다.
  4. 센서 다중 HAL 2.0 섹션의 3단계와 4단계를 따라 센서 다중 HAL 2.0을 지정 HAL로 설정합니다.

유효성 검사

VTS 실행

하나 이상의 하위 HAL을 센서 다중 Hal 2.1과 통합한 경우 공급업체 테스트 모음(VTS)을 사용하여, 하위 HAL 구현이 센서 HAL 인터페이스에 설정된 모든 요구사항을 충족하는지 확인합니다.

호스트 머신에 VTS가 설정되어 있을 때 센서 VTS 테스트만 실행하려면 다음 명령어를 실행합니다.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

AIDL 다중 HAL shim 레이어를 실행하는 경우 VtsAidlHalSensorsTargetTest를 실행합니다.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

단위 테스트 실행

HalProxy_test.cpp의 단위 테스트는 단위 테스트에 인스턴스화되고 동적으로 로드되지 않은 가짜 하위 HAL을 사용하여 HalProxy를 테스트합니다. 이 같은 테스트는 새로운 하위 HAL을 만들 때 새로운 하위 HAL이 제대로 구현되었는지 확인하는 단위 테스트의 추가 방법을 안내하는 역할을 하게 됩니다.

테스트를 실행하려면 다음 명령어를 실행합니다.

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

가짜 하위 HAL로 테스트

가짜 하위 HAL은 ISensorsSubHal 인터페이스의 모조 구현입니다. 하위 HAL은 서로 다른 센서 목록을 노출합니다. 센서는 활성화되면 관련 센서 요청에 지정된 간격에 따라 자동으로 생성된 센서 이벤트를 주기적으로 HalProxy에 게시합니다.

가짜 하위 HAL은 전체 다중 HAL 코드가 시스템에 로드된 다른 하위 HAL과 어떻게 작동하는지 테스트하고 센서 다중 HAL 코드의 다양한 측면에 스트레스를 주는 데 사용할 수 있습니다.

두 개의 가짜 하위 HAL은 hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/에 있습니다.

가짜 하위 HAL을 빌드하고 기기에 푸시하려면 다음 단계를 따르세요.

  1. 다음 명령어를 실행하여 서로 다른 가짜 하위 HAL 세 개를 빌드하고 기기에 푸시합니다.

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  2. /vendor/etc/sensors/hals.conf의 센서 HAL 구성을 가짜 하위 HAL 경로로 업데이트합니다.

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. HalProxy를 다시 시작하고 구성에 나열된 새 하위 HAL을 로드합니다.

    adb shell stop
    adb shell start
    

디버깅

개발자는 lshal 명령어를 사용하여 프레임워크를 디버그할 수 있습니다. 센서 HAL의 디버그 출력을 요청하려면 다음 명령어를 실행하세요.

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

그러면 HalProxy의 현재 상태와 하위 HAL의 정보가 터미널에 출력됩니다. 다음은 HalProxy 객체 및 가짜 하위 HAL의 명령어 결과를 보여주는 예입니다.

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

# of events on pending write queue에 지정된 숫자가 크면(1,000 이상) 센서 프레임워크에 작성되기 위해 대기 중인 이벤트가 많다는 의미입니다. 이는 센서 서비스가 교착 상태이거나 비정상 종료된 후 센서 이벤트를 처리하지 않는 중이거나, 최근에 대량의 센서 이벤트가 하위 HAL에서 게시되었음을 나타냅니다.

wake lock 참조 수가 0보다 크면 HalProxy가 wake lock을 획득했다는 의미입니다. ScopedWakelock이 의도적으로 유지되거나 wakeup 이벤트가 HalProxy로 전송된 후 센서 프레임워크에서 처리되지 않은 경우에만 0보다 커야 합니다.

HalProxy의 디버그 메서드에 전달된 파일 설명자가 각 하위 HAL에 전달되므로, 개발자는 디버그 메서드를 ISensorsSubHal 인터페이스의 일부로 구현해야 합니다.