센서 HAL 2.0

센서 하드웨어 추상화 계층(HAL)은 Android 센서 프레임워크, 그리고 가속도계 및 자이로스코프와 같은 기기 센서 사이의 인터페이스입니다. 센서 HAL은 프레임워크가 센서를 제어할 수 있도록 하기 위해 구현해야 하는 함수를 정의합니다.

Android 10 이상에서는 새 기기와 업그레이드된 기기에 대해 HAL 2.0이 제공됩니다. 센서 HAL 2.0은 센서 HAL 1.0에 기반하지만 역호환을 막는 몇 가지 중요한 차이점이 있습니다. 센서 HAL 2.0은 FMQ(Fast Message Queues)를 사용하여 HAL의 이벤트를 Android 센서 프레임워크로 전송합니다.

예시 및 소스

센서 HAL 2.0의 주요 문서 출처는 hardware/interfaces/sensors/2.0/ISensors.hal의 HAL 정의 내에 위치합니다. 이 페이지와 ISensors.hal 간의 요구사항이 충돌되는 경우 ISensors.hal의 요구사항을 사용하세요.

기본 구현은 hardware/interfaces/sensors/2.0/default에서 제공됩니다. 이전 버전의 센서 HAL과 달리 기본 구현은 참조용으로만 제공되며 제품과 함께 배송되면 안 됩니다. 이 기본 구현은 2개의 FMQ를 사용하여 프레임워크와 통신하는 개념을 보여줍니다.

센서 HAL 2.0 구현

센서 HAL 2.0을 구현하려면 개체가 ISensors 인터페이스를 구현하고 ISensors.hal에 정의된 모든 함수를 구현해야 합니다.

HAL 초기화

센서 HAL은 사용 전에 Android 센서 프레임워크로 초기화해야 합니다. 프레임워크는 initialize() 함수를 호출하여 3개(2개의 FMQ 설명자와 ISensorsCallback 개체에 대한 1개의 포인터)의 매개변수를 센서 HAL에 제공합니다.

HAL은 첫 번째 설명자를 사용하여 센서 이벤트를 프레임워크에 작성하는 데 사용되는 이벤트 FMQ를 생성합니다. HAL은 두 번째 설명자를 사용하여 HAL이 WAKE_UP 센서 이벤트의 wake lock을 해제할 때 동기화를 수행하는 데 사용되는 Wake Lock FMQ를 생성합니다. HAL은 불필요한 콜백 함수가 호출되지 않도록 ISensorsCallback 개체에 대한 포인터를 저장해야 합니다.

initialize() 함수는 센서 HAL을 초기화할 때 처음으로 호출되는 함수여야 합니다.

사용 가능한 센서 노출

기기에서 사용 가능한 모든 정적 센서 목록을 가져오려면 getSensorsList() 함수를 사용하세요. 이 함수는 각각 핸들로 고유하게 식별되는 센서 목록을 반환합니다. 센서의 핸들은 센서 HAL을 호스팅하는 프로세스가 재시작될 때 변경되면 안 됩니다. 핸들은 기기 재부팅 및 시스템 서버 재시작 전체에 걸쳐 변경될 수 있습니다.

여러 센서가 같은 센서 유형과 wake-up 속성을 공유하는 경우에는 목록의 첫 번째 센서가 '기본' 센서로 불리며, getDefaultSensor(int sensorType, bool wakeUp) API를 활용하는 애플리케이션으로 기본 센서가 반환됩니다.

센서 목록의 안정성

센서 HAL이 재시작된 이후에 데이터가 getSensorsList()에 의해 반환된 경우에는 재시작 전에 검색된 센서 목록에 비해 중요한 변경사항이 적용되었음을 의미하며, 프레임워크에서 Android 런타임 재시작을 트리거합니다. 센서 목록에 대한 중요한 변경사항으로는 핸들이 지정된 센서의 속성이 누락 또는 변경되었거나 새 센서가 도입된 경우 등이 포함됩니다. Android 런타임을 재시작하면 사용자가 지장을 받을 수 있지만 이는 필수입니다. 이는 애플리케이션의 전체 기간 동안 정적 센서가 변경되지 않는다는 Android API 계약을 Android 프레임워크에서 더 이상 충족할 수 없기 때문입니다. 또한 이로 인해 애플리케이션에서 전송한 활성 센서 요청을 프레임워크에서 재구성하지 못할 수도 있습니다. 따라서 HAL 공급업체는 피할 수 있는 센서 목록 변경을 예방하는 것이 좋습니다.

안정적인 센서 핸들을 보장하려면 HAL은 기기의 실제 센서를 핸들에 확정적으로 매핑해야 합니다. 센서 HAL 인터페이스에서 강요하는 구체적인 구현은 없지만 개발자에게는 이러한 요구사항을 충족할 수 있는 여러 옵션이 주어집니다.

예를 들어 센서 목록은 각 센서의 고정 속성(예: 공급업체, 모델 및 센서 유형) 조합을 사용하여 정렬할 수 있습니다. 또 다른 옵션은 기기의 정적 센서 집합이 하드웨어에 고정된다는 사실에 의존합니다. 따라서 HAL은 getSensorsList()에서 돌아오기 전에 모든 예상 센서가 언제 초기화를 완료했는지 알아야 합니다. 예상 센서 목록은 HAL 바이너리로 컴파일하거나 파일 시스템의 구성 파일에 저장할 수 있으며, 표시 순서는 안정적인 핸들을 가져오는 데 사용할 수 있습니다. 가장 좋은 해결 방법은 HAL의 구체적인 구현 세부정보에 따라 다르지만 핵심 요구사항은 센서 핸들이 HAL 재시작 전체에 걸쳐 변경되면 안 된다는 것입니다.

센서 구성

센서는 활성화되기 전에 batch() 함수를 통해 샘플링 기간 및 최대 보고 지연 시간으로 구성해야 합니다.

센서는 센서 데이터의 손실 없이 batch()를 통해 언제든지 재구성 가능해야 합니다.

샘플링 기간

샘플링 기간은 구성 중인 센서 유형에 따라 다른 의미를 지닙니다.

  • 연속: 센서 이벤트가 생성되는 속도입니다.
  • 변경 시: 이벤트 생성 속도가 샘플링 기간을 초과하지 않으며, 측정된 값이 변경되지 않을 경우 샘플링 기간보다 느리게 생성될 수 있습니다.
  • 원샷: 샘플링 기간이 무시됩니다.
  • 특수: 자세한 내용은 센서 유형 설명을 참조하세요.

샘플링 기간과 센서 보고 모드 간의 상호작용에 대한 자세한 내용은 보고 모드를 참조하세요.

최대 보고 지연 시간

최대 보고 지연 시간은 SoC가 활성화된 상태에서 이벤트가 HAL을 통해 이벤트 FMQ에 작성되기 전에 지연되고 하드웨어 FIFO에 저장될 수 있는 최대 시간(나노초)을 설정합니다.

값이 0인 경우 이벤트를 측정되는 즉시 보고해야 함을 의미합니다(FIFO를 아예 건너뛰거나 센서의 한 이벤트가 FIFO에 존재하는 즉시 FIFO를 비움).

예를 들어 가속도계가 최대 보고 지연 시간 0으로 50Hz에서 활성화되면 SoC가 활성화될 때 인터럽트가 초당 50회 트리거됩니다.

최대 보고 지연 시간이 0보다 큰 경우에는 이벤트를 감지되는 즉시 보고할 필요가 없습니다. 이벤트는 하드웨어 FIFO에 임시 보관하여 일괄 보고할 수 있습니다. 단, 이벤트가 최대 보고 지연 시간보다 길게 지연되면 안 됩니다. 이전 배치 이후의 모든 이벤트는 한 번에 기록 및 반환됩니다. 이렇게 하면 SoC로 전송되는 인터럽트 수가 감소하며, 센서가 데이터를 캡처하고 일괄 처리하는 동안 SoC가 저전력 모드로 전환될 수 있습니다.

각 이벤트에는 타임스탬프가 연결되어 있습니다. 이벤트가 보고되는 시간을 지연할 때 이벤트 타임스탬프가 영향을 받으면 안 됩니다. 타임스탬프를 정확해야 하며 이벤트가 보고된 시간이 아니라 이벤트가 실제로 발생한 시간과 일치해야 합니다.

최대 보고 지연 시간이 0이 아닌 센서 이벤트를 보고하는 과정에 대한 추가 정보와 요구사항은 일괄 처리를 참조하세요.

센서 활성화

프레임워크는 activate() 함수를 통해 센서를 사용 설정하고 사용 중지합니다. 프레임워크는 센서를 활성화하기 전에 먼저 batch()를 통해 센서를 구성해야 합니다.

센서가 비활성화되면 해당 센서의 추가 센서 이벤트가 이벤트 FMQ에 작성되면 안 됩니다.

플러시 센서

센서가 센서 데이터를 일괄 처리하도록 구성된 경우 프레임워크는 flush()를 호출하여 일괄 처리된 센서 이벤트에 대한 즉각적인 플러시를 강제할 수 있습니다. 이렇게 하면 지정된 센서 핸들에 대해 일괄 처리된 센서 이벤트가 이벤트 FMQ에 즉시 작성됩니다. 센서 HAL은 flush()의 결과로 작성되는 센서 이벤트 끝에 플러시 완료 이벤트를 추가해야 합니다.

플러시는 비동기식으로 발생합니다(이 함수가 즉시 반환되어야 함). 구현이 여러 센서에 FIFO를 사용하는 경우 해당 FIFO가 플러시되고 플러시 완료 이벤트가 지정된 센서에 대해서만 추가됩니다.

지정된 센서에 FIFO가 없거나(버퍼링 불가) 호출 시점에 FIFO가 비어 있었던 경우 flush()는 계속해서 성공해야 하며 해당 센서에 대한 플러시 완료 이벤트를 전송해야 합니다. 이는 원샷 센서를 제외한 모든 센서에 적용됩니다.

원샷 센서에 대해 flush()가 호출된 경우에는 flush()가 플러시 완료 이벤트를 생성하는 대신 BAD_VALUE를 반환해야 합니다.

센서 이벤트를 FMQ에 작성

이벤트 FMQ는 센서 HAL이 이벤트를 Android 센서 프레임워크로 푸시하기 위한 용도로 사용됩니다.

이벤트 FMQ는 동기화된 FMQ입니다. 즉, 가용한 공간을 초과하는 이벤트를 FMQ에 작성하려고 시도할 경우 작성에 실패합니다. 이 경우 HAL은 현재의 이벤트 집합을 2개의 소규모 이벤트 그룹으로 작성할지, 아니면 충분한 공간이 확보되었을 때 모든 이벤트를 함께 작성할지 결정해야 합니다.

센서 HAL이 원하는 수의 센서 이벤트를 이벤트 FMQ에 작성하면 센서 HAL은 이벤트 FMQ의 EventFlag::wake 함수에 EventQueueFlagBits::READ_AND_PROCESS 비트를 작성하여 프레임워크에 이를 알려야 합니다. EventFlag는 EventFlag::createEventFlag 및 이벤트 FMQ의 getEventFlagWord() 함수를 통해 이벤트 FMQ에서 생성할 수 있습니다.

센서 HAL 2.0은 이벤트 FMQ에서 writewriteBlocking을 모두 지원합니다. 기본 구현은 write를 사용하여 참조를 제공합니다. writeBlocking 함수가 사용되면 readNotification 플래그를 EventQueueFlagBits::EVENTS_READ로 설정해야 합니다. 이는 이벤트 FMQ의 이벤트가 판독되면 프레임워크에 의해 설정됩니다. 작성 알림 플래그는 EventQueueFlagBits::READ_AND_PROCESS로 설정해야 합니다. 그러면 이벤트가 이벤트 FMQ에 작성되었다는 내용을 프레임워크에서 전달받습니다.

WAKE_UP 이벤트

WAKE_UP 이벤트는 애플리케이션 프로세서(AP)가 활성화되어 즉시 이벤트를 처리하도록 하는 센서 이벤트입니다. WAKE_UP 이벤트가 이벤트 FMQ에 작성될 때마다 센서 HAL은 wake lock을 확보하여 프레임워크에서 이벤트를 처리할 수 있을 때까지 시스템이 활성화 상태를 유지하도록 해야 합니다. WAKE_UP 이벤트를 수신한 프레임워크는 센서 HAL이 wake lock을 해제할 수 있도록 자체 wake lock을 확보합니다. 센서 HAL이 wake lock을 해제할 때 동기화를 수행하려면 Wake Lock FMQ를 사용하세요.

센서 HAL은 Wake Lock FMQ를 판독하여 프레임워크에서 처리한 WAKE_UP 이벤트 수를 파악해야 합니다. HAL은 처리되지 않은 WAKE_UP 이벤트의 총 개수가 0인 경우에만 WAKE_UP 이벤트의 wake lock을 해제해야 합니다. 프레임워크는 센서 이벤트를 처리한 후 WAKE_UP 이벤트로 표시된 이벤트 수를 계산하고 이 수치를 다시 Wake Lock FMQ에 작성합니다.

프레임워크는 Wake Lock FMQ에 데이터를 작성할 때마다 Wake Lock FMQ에 WakeLockQueueFlagBits::DATA_WRITTEN 작성 알림을 설정합니다.

동적 센서

동적 센서는 기기의 실제 일부는 아니지만 가속도계를 포함하는 게임패드처럼 기기에 대한 입력으로 사용할 수 있는 센서입니다.

동적 센서가 연결되면 ISensorsCallbackonDynamicSensorConnected 함수가 센서 HAL에서 호출되어야 합니다. 그러면 프레임워크가 새로운 동적 센서에 대한 알림을 수신하며, 프레임워크를 통해 센서를 제어하고 센서 이벤트가 클라이언트에 의해 소비되도록 만들 수 있습니다.

마찬가지로 동적 센서가 연결 해제되면 프레임워크가 더 이상 사용할 수 없는 모든 센서를 제거할 수 있도록 ISensorsCallbackonDynamicSensorDisconnected 함수가 호출되어야 합니다.

직접 채널

직접 채널은 센서 이벤트가 Android 센서 프레임워크를 우회하여 이벤트 FMQ에 작성되는 대신 구체적인 메모리에 작성되는 연산 방식입니다. 직접 채널을 등록하는 클라이언트는 직접 채널을 생성하는 데 사용된 메모리에서 직접 센서 이벤트를 읽어야 하며, 프레임워크를 통해 센서 이벤트를 수신하지 않습니다. configDirectReport() 함수는 일반 연산의 경우 batch()와 유사하며, 직접 보고 채널을 구성합니다.

registerDirectChannel()unregisterDirectChannel() 함수는 새로운 직접 채널을 생성하거나 삭제합니다.

연산 모드

setOperationMode() 함수는 프레임워크가 센서 데이터를 센서에 삽입할 수 있도록 센서를 구성할 수 있게 해줍니다. 이는 테스트, 특히 프레임워크 아래에 존재하는 알고리즘에 유용합니다.

injectSensorData() 함수는 보통 연산 매개변수를 센서 HAL로 푸시하는 데 사용됩니다. 이 함수는 센서 이벤트를 구체적인 센서에 삽입하는 데에도 사용할 수 있습니다.

유효성 검사

센서 HAL을 검증하려면 CTS 및 VTS 테스트를 실행하세요.

CTS 테스트

CTS 테스트는 자동화된 CTS 테스트와 수동 CTS 인증기 애플리케이션 둘 다에 존재합니다.

자동화된 테스트는 cts/tests/sensor/src/android/hardware/cts에 있습니다. 이 테스트는 센서 활성화, 일괄 처리 및 센서 이벤트 비율과 같은 센서의 일반적인 기능을 검증합니다.

CTS 인증기 테스트는 cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors에 있습니다. 이 테스트에는 테스트 운영자의 수동 입력이 필요하며, 센서가 정확한 값을 보고하는지 확인합니다.

테스트 대상 기기는 CTS 테스트에 합격해야만 모든 CDD 요구사항을 충족할 수 있습니다.

VTS 테스트

센서 HAL 2.0 관련 VTS 테스트는 hardware/interfaces/sensors/2.0/vts에 있습니다. 이 테스트는 센서 HAL이 제대로 구현되었는지, ISensors.halISensorsCallback.hal 내의 모든 요구사항이 제대로 충족되었는지 확인합니다.

1.0에서 센서 HAL 2.0으로 업그레이드

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

HAL 초기화

프레임워크와 HAL 간의 FMQ가 수립되도록 initialize() 함수를 지원해야 합니다.

사용 가능한 센서 노출

센서 HAL 2.0에서는 getSensorsList() 함수가 모든 센서 HAL 재시작에 걸쳐 단일 기기 부팅 도중의 동일한 값을 반환해야 합니다. getSensorsList() 함수의 새로운 요구사항은 이 함수가 모든 센서 HAL 재시작에 걸쳐 단일 기기 부팅 도중의 동일한 값을 반환해야 한다는 것입니다. 그러면 프레임워크는 시스템 서버거 재시작될 경우 센서 연결을 다시 시도할 수 있습니다. getSensorsList()에 의해 반환된 값은 기기가 재부팅을 수행한 후에 변경할 수 있습니다.

센서 이벤트를 FMQ에 작성

센서 HAL 2.0에서는 poll()이 호출되기를 기다리는 대신 센서 이벤트가 준비될 때마다 센서 HAL이 미리 센서 이벤트를 이벤트 FMQ에 작성해야 합니다. 또한 HAL은 올바른 비트를 EventFlag에 작성하여 프레임워크 내에서 FMQ 판독이 발생하도록 해야 합니다.

WAKE_UP 이벤트

센서 HAL 1.0에서는 WAKE_UPpoll()에 게시된 이후에 HAL이 poll()에 대한 모든 후속 호출에 대한 모든 WAKE_UP 이벤트의 wake lock을 해제할 수 있었습니다. 이는 프레임워크에서 모든 센서 이벤트를 처리했고 필요한 경우 wake lock을 획득했음을 나타내기 때문입니다. 센서 HAL 2.0에서는 프레임워크가 FMQ에 작성된 이벤트를 처리했을 때 HAL이 더 이상 이를 알지 못합니다. 따라서 Wake Lock FMQ는 프레임워크가 WAKE_UP 이벤트를 처리했을 때 이를 HAL에 통신할 수 있도록 합니다.

센서 HAL 2.0에서는 WAKE_UP 이벤트와 관련하여 센서 HAL이 확보한 wake lock이 SensorsHAL_WAKEUP으로 시작되어야 합니다.

동적 센서

센서 HAL 1.0에서는 동적 센서가 poll() 함수를 통해 반환되었습니다. 센서 HAL 2.0은 동적 센서 연결이 변경될 때마다 ISensorsCallbackonDynamicSensorsConnectedonDynamicSensorsDisconnected가 호출되도록 요구합니다. 이러한 콜백은 initialize() 함수를 통해 제공되는 ISensorsCallback 포인트의 일부로 제공됩니다.

연산 모드

WAKE_UP 센서의 DATA_INJECTION 모드가 센서 HAL 2.0에서 지원되어야 합니다.

다중 HAL 지원

Android 센서 프레임워크는 다중 HAL을 포함하는 센서 HAL 2.0을 기본으로 지원하지 않습니다.