Android 13 및 이후 버전을 실행하는 기기에 제공되는 헤드 추적기 인간 인터페이스 기기(HID) 프로토콜을 사용하면 헤드 추적 기기를 USB 또는 블루투스를 통해 Android 기기에 연결하고 센서 프레임워크를 통해 Android 프레임워크 및 앱에 노출할 수 있습니다. 이 프로토콜은 오디오 가상화기 효과(3D 오디오)를 제어하는 데 사용됩니다. 이 페이지에서는 기기와 호스트라는 용어를 블루투스 관련 의미로 사용하며 기기는 헤드 추적 기기를, 호스트는 Android 호스트를 의미합니다.
기기 제조업체는 헤드 추적기 HID 프로토콜을 지원할 수 있도록 Android 기기를 구성해야 합니다. 구성에 관한 자세한 내용은 동적 센서 리드미를 참고하세요.
이 페이지에서는 다음 리소스에 익숙하다고 가정합니다.
최상위 구조
Android 프레임워크는 헤드 추적기 기기를 HID 기기로 식별합니다.
유효한 HID 설명자의 전체 예는 부록 1: HID 설명자의 예를 참고하세요.
최상위 수준에서 헤드 추적기 기기는 Sensors
페이지(0x20
)와 Other: Custom
사용(0xE1
)이 있는 앱 컬렉션입니다. 이 컬렉션 내에는 여러 데이터 필드(입력) 및 속성(기능)이 있습니다.
속성 및 데이터 필드
이 섹션에서는 헤드 추적기 기기의 애플리케이션 컬렉션에 포함된 속성과 데이터 필드를 설명합니다.
속성: 센서 설명(0x0308
)
센서 설명(0x0308
) 속성은 다음 값을 포함해야 하는 읽기 전용 ASCII(8비트) 문자열 속성입니다.
#AndroidHeadTracker#1.0
null 종결자가 없을 것으로 예상됩니다. 즉, 이 속성의 총 크기는 8비트 문자 23개입니다.
이 속성은 다른 맞춤 센서와의 충돌을 방지하기 위한 분류자 역할을 합니다.
속성: 영구 고유 ID(0x0302
)
영구 고유 ID(0x0302
) 속성은 16개 요소의 읽기 전용 배열로, 각각 8비트(총 128비트)입니다. null 종결자가 없을 것으로 예상됩니다. 이 속성은 선택사항입니다.
이 속성을 사용하면 오디오 기기에 통합된 헤드 추적 기기가 이와 연결된 오디오 기기를 참조할 수 있습니다. 다음과 같은 스키마가 지원됩니다.
독립형 헤드 추적기
영구 고유 ID(0x0302
) 속성이 존재하지 않거나 모두 0으로 설정된 경우 헤드 추적기 기기는 오디오 기기에 영구적으로 연결되지 않으며 별도로 사용될 수 있습니다. 예를 들어 사용자가 헤드 추적기 기기를 별도의 오디오 기기와 수동으로 연결할 수 있습니다.
블루투스 MAC 주소를 사용한 참조
옥텟 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
값 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | B | T | 블루투스 MAC |
이 스키마에서 처음 8개의 옥텟은 0
이어야 하고 옥텟 8과 9는 각각 ASCII 값 B
와 T
를 포함해야 하며 다음 6개의 옥텟은 블루투스 MAC 주소로 해석됩니다(헤드 추적기 기기가 이 MAC 주소를 갖는 모든 오디오 기기에 적용된다고 가정).
UUID를 사용한 참조
옥텟 8의 최상위 비트(MSB)가 설정될 때마다(≥0x80
) 필드는 RFC-4122에 지정된 대로 UUID로 해석됩니다. 상응하는 오디오 기기는 Android 프레임워크에 등록된 동일한 UUID를 사용된 전송 유형과 관련된 지정되지 않은 메커니즘을 통해 제공합니다.
속성: 보고 상태(0x0316
)
보고 상태(0x0316
) 속성은 HID 사양에 정의된 표준 시맨틱이 있는 읽기/쓰기 속성입니다. 호스트는 이 속성을 사용하여 보고할 이벤트를 기기에 나타냅니다. No Events(0x0840
) 및 All Events(0x0841
) 값만 사용됩니다.
이 필드의 초깃값은 No Events여야 하고 기기에서 수정해서는 안 되며 호스트에서만 수정해야 합니다.
속성: 전원 상태(0x0319
)
전원 상태(0x0319
) 속성은 HID 사양에 정의된 표준 시맨틱이 있는 읽기/쓰기 속성입니다. 호스트는 이 속성을 사용하여 기기가 있어야 할 전원 상태를 기기에 나타냅니다. Full Power(0x0851
) 및 Power Off(0x0855
) 값만 사용됩니다.
이 필드의 초깃값은 기기에서 결정되고 기기에서 수정해서는 안 되며 호스트에서만 수정해야 합니다.
속성: 보고서 간격(0x030E
)
보고서 간격(0x030E
) 속성은 HID 사양에 정의된 표준 시맨틱이 있는 읽기/쓰기 속성입니다. 호스트는 이 속성을 사용하여 데이터 판독값을 보고하는 빈도를 기기에 나타냅니다.
단위는 초입니다. 이 값의 유효한 범위는 기기에서 결정하며 실제 최소/최대 메커니즘을 사용하여 설명됩니다. 최소 50Hz 보고 속도가 지원되어야 하며 권장 최대 보고 속도는 100Hz입니다. 따라서 최소 보고 간격은 20ms 이하여야 하고, 10ms 이상인 것이 좋습니다.
데이터 필드: 맞춤 값 1(0x0544
)
맞춤 값 1(0x0544
) 필드는 실제 헤드 추적 정보를 보고하는 데 사용되는 입력란입니다. 이는 HID 사양의 섹션 6.2.2.7에 지정된 대로 실제 값의 일반 HID 규칙에 따라 해석된 3요소 배열입니다. 각 요소의 유효한 범위는 [-π, π] rad입니다. 단위는 항상 라디안입니다.
요소는 [rx, ry, rz]
로 해석됩니다. [rx, ry, rz]
는 회전 벡터로, 참조 프레임에서 헤드 프레임으로의 변환을 나타냅니다.
크기는 [0..π] 범위 내에 있어야 합니다.
참조 프레임은 임의적이지만 일반적으로 고정되어 있고 오른쪽에 있어야 합니다. 약간의 드리프트가 허용됩니다. 헤드 축은 다음과 같습니다.
- 왼쪽 귀에서 오른쪽 귀까지 X
- 머리 뒤에서 코까지 Y(뒤에서 앞으로)
- 목에서 머리 상단까지 Z
데이터 필드: 맞춤 값 2(0x0545
)
맞춤 값 2(0x0545
) 필드는 실제 헤드 추적 정보를 보고하는 데 사용되는 입력란입니다. 이는 실제 값의 일반 HID 규칙에 따라 해석된 3요소로 구성된 고정 소수점 배열입니다.
단위는 항상 라디안/초입니다.
요소는 [vx, vy, vz]
로 해석됩니다. [vx, vy, vz]
는 회전 벡터로, 헤드 프레임의 각 속도를 나타냅니다(자체에 상대적).
데이터 필드: 맞춤 값 3(0x0546
)
맞춤 값 3(0x0546
) 필드는 참조 프레임의 불연속성을 추적하는 데 사용되는 입력란입니다. 크기가 스칼라 정수 8비트입니다. 예를 들어 방향을 확인하는 데 사용되는 방향 필터 알고리즘의 상태가 재설정된 경우와 같이 참조 프레임이 변경될 때마다 기기에서 증분(랩어라운드로)되어야 합니다. 이 값은 실제 값의 일반 HID 규칙에 따라 해석됩니다. 하지만 실제 값과 단위는 중요하지 않습니다. 호스트와 관련된 유일한 정보는 변경된 값입니다. 논리 단위에서 실제 단위로 변환하는 동안 정밀도의 손실과 관련된 숫자 문제를 방지하려면 이 필드의 실제 최솟값, 실제 최댓값, 단위 지수 값을 0으로 설정하는 것이 좋습니다.
보고서 구조
보고서 ID를 할당하여 속성을 보고서로 유연하게 그룹화할 수 있습니다. 효율성을 위해 읽기 전용 속성을 읽기/쓰기 속성과 분리하는 것이 좋습니다.
데이터 필드의 경우 맞춤 값 1, 2, 3 필드는 동일한 보고서에 있어야 하며 특정 기기(앱 컬렉션)의 보고서 하나에만 있어야 합니다.
입력 보고서 전송
기기는 다음 조건이 모두 충족되면 HID INPUT 메시지를 통해 주기적으로 그리고 비동기적으로 입력 보고서를 전송해야 합니다.
- 전원 상태 속성이 Full Power로 설정되어 있습니다.
- 보고 상태 속성이 All Events로 설정되어 있습니다.
- 보고 간격 속성이 0이 아닙니다.
보고 간격 속성은 보고서 전송 빈도를 결정합니다. 위 조건 중 하나라도 충족하지 않는 경우 기기는 어떠한 보고서도 전송하면 안 됩니다.
향후 호환성 및 하위 호환성
헤드 추적기 HID 프로토콜은 업데이트를 허용하는 버전 관리 스키마를 사용하는 동시에, 다른 버전의 프로토콜을 사용하는 호스트와 기기 간의 상호 운용성을 허용합니다. 프로토콜 버전은 다음 섹션에 설명된 것과 같이 고유한 시맨틱이 있는 두 가지 숫자(메이저 버전 및 마이너 버전)로 식별됩니다.
기기에서 지원하는 버전은 센서 설명(0x0308
) 속성을 검사하여 확인할 수 있습니다.
마이너 버전 호환성
마이너 버전의 변경사항은 동일한 메이저 버전을 기반으로 하는 이전 마이너 버전과 호환됩니다. 마이너 버전 업데이트에서 호스트는 추가 데이터 필드와 속성을 무시합니다. 예를 들어 프로토콜 버전 1.6을 사용하는 기기는 버전 1.5 등 프로토콜 버전 1.x를 지원하는 호스트와 호환됩니다.
메이저 버전 호환성
이전 버전과 호환되지 않는 변경사항은 메이저 버전 변경사항으로 허용됩니다. 이전 호스트 및 새 호스트와의 상호 운용성을 위한 여러 메이저 버전을 지원하기 위해 기기는 보고서 설명자에서 여러 앱 컬렉션을 지정할 수 있습니다. 예:
const unsigned char ReportDescriptor[] = {
HID_USAGE_PAGE_SENSOR,
HID_USAGE_SENSOR_TYPE_OTHER_CUSTOM,
HID_COLLECTION(HID_APPLICATION),
// Feature report 2 (read-only).
HID_REPORT_ID(2),
// Magic value: "#AndroidHeadTracker#1.5"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(23),
HID_FEATURE(HID_CONST_VAR_ABS),
...
HID_END_COLLECTION,
HID_COLLECTION(HID_APPLICATION),
// Feature report 12 (read-only).
HID_REPORT_ID(12),
// Magic value: "#AndroidHeadTracker#2.4"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(23),
HID_FEATURE(HID_CONST_VAR_ABS),
...
HID_END_COLLECTION,
};
이 경우 호스트는 기기에서 광고하는 다양한 앱 컬렉션을 모두 열거하므로 Sensor Description 속성을 검사하여 각각 구현하는 프로토콜 버전을 확인한 후 호스트에서 지원하는 최신 프로토콜 버전을 선택할 수 있습니다. 선택하면 호스트는 기기 연결의 전체 기간 동안 선택된 단일 프로토콜로 작동합니다.
부록: HID 설명자의 예
다음 예는 일반적인 유효한 HID 설명자를 보여줍니다. HID 센서 사용(섹션 4.1)에 제공된 일반적으로 사용되는 C 매크로를 사용합니다.
const unsigned char ReportDescriptor[] = {
HID_USAGE_PAGE_SENSOR,
HID_USAGE_SENSOR_TYPE_OTHER_CUSTOM,
HID_COLLECTION(HID_APPLICATION),
// Feature report 2 (read-only).
HID_REPORT_ID(2),
// Magic value: "#AndroidHeadTracker#1.0"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(23),
HID_FEATURE(HID_CONST_VAR_ABS),
// UUID.
HID_USAGE_SENSOR_PROPERTY_PERSISTENT_UNIQUE_ID,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(16),
HID_FEATURE(HID_CONST_VAR_ABS),
// Feature report 1 (read/write).
HID_REPORT_ID(1),
// 1-bit on/off reporting state.
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(1),
HID_REPORT_SIZE(1),
HID_REPORT_COUNT(1),
HID_COLLECTION(HID_LOGICAL),
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE_NO_EVENTS,
HID_USAGE_SENSOR_PROPERTY_REPORTING_STATE_ALL_EVENTS,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// 1-bit on/off power state.
HID_USAGE_SENSOR_PROPERTY_POWER_STATE,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(1),
HID_REPORT_SIZE(1),
HID_REPORT_COUNT(1),
HID_COLLECTION(HID_LOGICAL),
HID_USAGE_SENSOR_PROPERTY_POWER_STATE_D4_POWER_OFF,
HID_USAGE_SENSOR_PROPERTY_POWER_STATE_D0_FULL_POWER,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// 6-bit reporting interval, with values [0x00..0x3F] corresponding to [10ms..100ms].
HID_USAGE_SENSOR_PROPERTY_REPORT_INTERVAL,
HID_LOGICAL_MIN_8(0x00),
HID_LOGICAL_MAX_8(0x3F),
HID_PHYSICAL_MIN_8(10),
HID_PHYSICAL_MAX_8(100),
HID_REPORT_SIZE(6),
HID_REPORT_COUNT(1),
HID_USAGE_SENSOR_UNITS_SECOND,
HID_UNIT_EXPONENT(0xD), // 10^-3
HID_FEATURE(HID_DATA_VAR_ABS),
// Input report 1
// Orientation as rotation vector (scaled to [-pi..pi] rad).
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_1,
HID_LOGICAL_MIN_16(0x01, 0x80), // LOGICAL_MINIMUM (-32767)
HID_LOGICAL_MAX_16(0xFF, 0x7F), // LOGICAL_MAXIMUM (32767)
HID_PHYSICAL_MIN_32(0x60, 0x4F, 0x46, 0xED), // -314159265
HID_PHYSICAL_MAX_32(0xA1, 0xB0, 0xB9, 0x12), // 314159265
HID_UNIT_EXPONENT(0x08), // 10^-8
HID_REPORT_SIZE(16),
HID_REPORT_COUNT(3),
HID_INPUT(HID_DATA_VAR_ABS),
// Angular velocity as rotation vector (scaled to [-32..32] rad/sec).
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_2,
HID_LOGICAL_MIN_16(0x01, 0x80), // LOGICAL_MINIMUM (-32767)
HID_LOGICAL_MAX_16(0xFF, 0x7F), // LOGICAL_MAXIMUM (32767)
HID_PHYSICAL_MIN_8(0xE0),
HID_PHYSICAL_MAX_8(0x20),
HID_UNIT_EXPONENT(0x00), // 10^0
HID_REPORT_SIZE(16),
HID_REPORT_COUNT(3),
HID_INPUT(HID_DATA_VAR_ABS),
// Reference frame reset counter.
HID_USAGE_SENSOR_DATA_CUSTOM_VALUE_3,
HID_LOGICAL_MIN_16(0x00, 0x00), // LOGICAL_MINIMUM (0)
HID_LOGICAL_MAX_16(0xFF, 0x00), // LOGICAL_MAXIMUM (255)
HID_PHYSICAL_MIN_8(0x00),
HID_PHYSICAL_MAX_8(0x00),
HID_UNIT_EXPONENT(0x00), // 10^0
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(1),
HID_INPUT(HID_DATA_VAR_ABS),
HID_END_COLLECTION,
};