O protocolo de dispositivo de interface humana (HID, na sigla em inglês) do rastreador principal, disponível para dispositivos com o Android 13 e versões mais recentes, permite que um dispositivo desse tipo seja conectado a um dispositivo Android por USB ou Bluetooth e seja exposto ao framework e aos apps do Android usando o framework de sensores. Esse protocolo é usado para controlar um efeito de virtualizador de áudio (áudio 3D). Esta página usa os termos dispositivo e host no sentido de Bluetooth, em que dispositivo significa o dispositivo de rastreamento da cabeça e host significa o host do Android.
Os fabricantes precisam configurar os dispositivos Android para ativar o suporte ao protocolo HID do rastreador de posições da cabeça. Para informações mais detalhadas sobre a configuração, consulte o README dos sensores dinâmicos (em inglês).
Para acessar esta página, você precisa estar familiarizado com os seguintes recursos:
Estrutura de nível superior
O framework do Android identifica o dispositivo de monitor da posição da cabeça como um dispositivo HID.
Para conferir um exemplo completo de um descritor HID válido, consulte Apêndice 1: exemplo de um descritor HID.
No nível superior, o dispositivo rastreador principal é uma coleção de apps com a
página Sensors
(0x20
) e o uso de Other: Custom
(0xE1
). Dentro dessa
coleção há vários campos de dados (entradas) e propriedades (recursos).
Propriedades e campos de dados
Esta seção descreve as propriedades e os campos de dados em uma coleção de aplicativos de um dispositivo rastreador principal.
Propriedade: descrição do sensor (0x0308
)
A propriedade Sensor Description (0x0308
) é uma propriedade de string ASCII (8 bits)
de leitura somente, que precisa conter os seguintes valores:
Versão 1.0 do monitor de posições da cabeça:
#AndroidHeadTracker#1.0
Tracker da cabeça versão 2.0 (disponível no Android 15 ou mais recente), que inclui suporte ao LE Audio:
#AndroidHeadTracker#2.0#x
O x
é um número inteiro (1
, 2
, 3
) que indica o transporte de suporte:
- 1: ACL
- 2: ISO
- 3: ACL + ISO
Nenhum terminador nulo é esperado, o que significa que o tamanho total dessa propriedade é de 23 caracteres de 8 bits para a versão 1.0.
Essa propriedade serve como um discriminador para evitar colisões com outros sensores personalizados.
Propriedade: ID exclusivo persistente (0x0302
)
A propriedade de ID exclusivo persistente (0x0302
) é uma matriz somente leitura de 16 elementos, de 8 bits cada (total de 128 bits). Nenhum terminador nulo é esperado. Essa
propriedade é opcional.
Essa propriedade permite que dispositivos de rastreamento da cabeça integrados a dispositivos de áudio façam referência ao dispositivo de áudio ao qual estão conectados. Há suporte para os esquemas a seguir.
Rastreador de cabeça independente
Se a propriedade Persistent Unique ID (0x0302
) não existir ou estiver definida como todos
zeros, significa que o dispositivo de rastreamento da cabeça não está permanentemente conectado a um
dispositivo de áudio e pode ser usado separadamente, por exemplo, permitindo que o usuário
associe manualmente o dispositivo de rastreamento da cabeça a um dispositivo de áudio separado.
Referência usando endereço MAC do Bluetooth
Octeto | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Valor | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | B | T | MAC do Bluetooth |
Nesse esquema, os primeiros 8 octetos precisam ser 0
, os octetos 8 e os 9 precisam conter
os valores ASCII B
e T
, respectivamente, e os seis octetos a seguir são interpretados como um endereço MAC Bluetooth, supondo que o dispositivo de rastreamento principal
se aplique a qualquer dispositivo de áudio que tenha esse endereço MAC. Esse endereço precisa ser o
endereço de identidade, mesmo que o dispositivo use um endereço MAC aleatório para estabelecer
conexões. Os dispositivos de modo duplo que se conectam por Bluetooth clássico
(formato HID v1.0) e Bluetooth LE (formato HID v2.0) precisam expor dois descritores
HID com o mesmo endereço de identidade. Dispositivos de modo duplo com dispositivos
esquerdo e direito separados precisam expor o Bluetooth LE HID usando o dispositivo dual
principal em vez do dispositivo secundário somente LE.
Referência usando UUID
Sempre que o bit mais significativo (MSB) do octeto 8 é definido (≥0x80
), o campo é interpretado como um UUID, conforme especificado no RFC-4122. O
dispositivo de áudio correspondente fornece o mesmo UUID, que é registrado no
framework do Android, por um mecanismo não especificado específico do
tipo de transporte usado.
Propriedade: estado do relatório (0x0316
)
A propriedade de estado do relatório (0x0316
) é uma propriedade de leitura/gravação que tem a
semântica padrão, conforme definido na especificação HID. O host usa essa
propriedade para indicar ao dispositivo quais eventos relatar. Somente os valores "No Events" (0x0840
) e "All Events" (0x0841
) são usados.
O valor inicial desse campo precisa ser "Sem eventos" e nunca ser modificado pelo dispositivo, apenas pelo host.
Propriedade: estado de energia (0x0319
)
A propriedade de estado de energia (0x0319
) é uma propriedade de leitura/gravação que tem a
semântica padrão, conforme definido na especificação HID. O host usa essa
propriedade para indicar ao dispositivo em que estado de energia ele precisa estar. Somente os
valores "Full Power" (0x0851
) e "Power Off" (0x0855
) são usados.
O valor inicial desse campo é determinado pelo dispositivo e nunca pode ser modificado por ele, apenas pelo host.
Propriedade: intervalo do relatório (0x030E
)
A propriedade Intervalo de relatório (0x030E
) é uma propriedade de leitura/gravação que tem a
semântica padrão conforme definido na especificação HID. O host usa essa
propriedade para indicar ao dispositivo com que frequência relata as leituras de dados.
As unidades são informadas em segundos. O intervalo válido para esse valor é determinado pelo dispositivo
e descrito usando o mecanismo mínimo/máximo físico. É necessário oferecer suporte a uma taxa de relatório de pelo menos 50 Hz, e a taxa máxima recomendada é de 100 Hz. Portanto, o intervalo mínimo de relatório precisa ser menor ou igual a 20 ms, e é recomendável que seja maior ou igual a 10 ms.
Propriedade: transporte LE reservado pelo fornecedor (0xF410
)
A propriedade LE Transport reservada pelo fornecedor (0xF410
) é uma propriedade de leitura/gravação
que tem a semântica padrão, conforme definido na especificação HID. O host
usa essa propriedade para indicar o transporte selecionado (ACL ou ISO). Somente os
valores ACL (0xF800
) e ISO (0xF801
) são usados, e ambos precisam ser incluídos
na coleção lógica.
Essa propriedade é configurada antes dos estados de energia ou de geração de relatórios.
Campo de dados: valor personalizado 1 (0x0544
)
O campo Valor personalizado 1 (0x0544
) é um campo de entrada usado para informar as
informações reais de rastreamento de cabeça. É uma matriz de três elementos, interpretada de acordo com as regras HID normais para valores físicos, conforme especificado na seção 6.2.2.7 da especificação do HID. O intervalo válido para cada elemento é [-π, π] rad. As unidades
são sempre radianos.
Os elementos são interpretados como: [rx, ry, rz]
, de modo que [rx, ry, rz]
seja um
vetor de rotação,
que representa a transformação do frame de referência para o principal.
A magnitude precisa estar no intervalo [0..π].
O frame de referência é arbitrário, mas geralmente é fixo e precisa ser direito. Uma pequena quantidade de deriva é aceitável. Os eixos da cabeça são:
- X da orelha esquerda para a direita
- Y da parte de trás da cabeça até o nariz (de trás para a frente)
- Z do pescoço até o topo da cabeça
Campo de dados: valor personalizado 2 (0x0545
)
O campo "Valor personalizado 2" (0x0545
) é um campo de entrada usado para informar as
informações reais de rastreamento de cabeça. É uma matriz de ponto fixo de três elementos,
interpretada de acordo com as regras HID normais para valores físicos.
As unidades são sempre radianos/segundo.
Os elementos são interpretados como: [vx, vy, vz]
, de modo que [vx, vy, vz]
é um
vetor de rotação,
que representa a velocidade angular do frame principal (em relação a si mesmo).
Campo de dados: valor personalizado 3 (0x0546
)
O campo "Valor personalizado 3" (0x0546
) é um campo de entrada usado para rastrear descontinuidades no frame de referência. É um número inteiro escalar de 8 bits. Ela precisa ser incrementada (com a volta) pelo dispositivo sempre que o
frame de referência for mudado. Por exemplo, se um algoritmo de filtro de orientação
usado para determinar a orientação tiver o estado redefinido. Esse valor é
interpretado de acordo com as regras normais de HID para valores físicos. No entanto, o valor físico e as unidades não importam. A única informação relevante para o host é um valor alterado. Para evitar problemas numéricos relacionados à perda de precisão
ao converter de unidades lógicas para físicas, é recomendável definir os
valores de mínimo físico, máximo físico e expoente de unidade como zero para esse campo.
Estrutura do relatório
O agrupamento de propriedades em relatórios (por atribuição de IDs de relatórios) é flexível. Para eficiência, recomendamos separar as propriedades somente leitura das propriedades de leitura/gravação.
Para os campos de dados, os campos dos valores personalizados 1, 2 e 3 precisam estar no mesmo relatório e em apenas um relatório para determinado dispositivo (coleção de apps).
Enviar relatórios de entrada
O dispositivo precisa enviar relatórios de entrada de forma periódica e assíncrona (por mensagens HID INPUT) quando todas estas condições forem atendidas:
- A propriedade "Estado de energia" está definida como "Potência total".
- A propriedade "Estado do relatório" está definida como "Todos os eventos".
- A propriedade Intervalo do relatório é diferente de zero.
A propriedade "Intervalo do relatório" determina a frequência de envio dos relatórios. Quando qualquer uma das condições acima não for atendida, o dispositivo não poderá enviar relatórios.
Compatibilidade com versões anteriores e futuras
O protocolo HID do rastreador de posições da cabeça usa um esquema de controle de versões que permite atualizações, além de permitir a interoperabilidade entre um host e um dispositivo que usa versões diferentes do protocolo. As versões do protocolo são identificadas por dois números, principal e secundário, que têm semânticas distintas, conforme descrito nas seções a seguir.
As versões compatíveis com um dispositivo podem ser determinadas examinando
a propriedade "Descrição do sensor" (0x0308
).
Compatibilidade de versão secundária
As mudanças na versão secundária são compatíveis com versões secundárias anteriores com base na mesma versão principal. Nas atualizações para a versão secundária, o host ignora campos e propriedades de dados adicionais. Por exemplo, um dispositivo que usa a versão 1.6 do protocolo é compatível com um host que oferece suporte à versão 1.x do protocolo, incluindo a versão 1.5.
Compatibilidade da versão principal
Mudanças não compatíveis com versões anteriores são permitidas para mudanças em versões principais. Para oferecer suporte a várias versões principais para interoperabilidade com hosts antigos e novos, os dispositivos podem especificar várias coleções de apps nos descritores do relatório. Exemplo:
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,
};
Nesse caso, o host pode enumerar todas as diferentes coleções de apps divulgadas pelo dispositivo, examinando a propriedade "Sensor Description" para determinar as versões de protocolo que cada uma implementa e escolhendo a versão mais recente do protocolo compatível com o host. Quando escolhido, o host funciona com o único protocolo escolhido para o ciclo de vida da conexão do dispositivo.
Apêndice: exemplo de um descritor HID
O exemplo a seguir ilustra um descritor HID válido típico. Ele usa as macros C usadas com frequência, fornecidas em Usos do sensor HID (seção 4.1).
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,
};
Apêndice 2: exemplo de um descritor HID v2.0
O exemplo a seguir ilustra um descritor HID v2.0 para um dispositivo que aceita apenas o transporte Bluetooth LE ACL.
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#2.0#1"
HID_USAGE_SENSOR_PROPERTY_SENSOR_DESCRIPTION,
HID_LOGICAL_MIN_8(0),
HID_LOGICAL_MAX_8(0xFF),
HID_REPORT_SIZE(8),
HID_REPORT_COUNT(25),
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),
// 1-bit transport selection
HID_USAGE_SENSOR_PROPERTY_VENDOR_LE_TRANSPORT,
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_VENDOR_LE_TRANSPORT_ACL,
HID_USAGE_SENSOR_PROPERTY_VENDOR_LE_TRANSPORT_ISO,
HID_FEATURE(HID_DATA_ARR_ABS),
HID_END_COLLECTION,
// 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,
};