Este artigo descreve como processar entradas rotativas no VHAL, configurar sua compilação para incluir o serviço rotativo e como personalizar a experiência rotativa em todos os aplicativos. Para aplicativos OEM pré-instalados, como um inicializador fornecido pelo OEM, consulte Car UI Library (car-ui-library) .
VHAL
Um controlador rotativo suporta as seguintes ações:
- Empurre para cima, para baixo, para a esquerda e para a direita.
- Gire no sentido horário e anti-horário.
- Pressione o botão central.
- Pressione o botão Voltar.
- Pressione o botão Início.
- Pressione outros botões, como Telefone e Mídia.
Consulte hardware/interfaces/automotive/vehicle/2.0/types.hal
para documentação sobre as propriedades do sistema e int32Values
correspondentes.
O VHAL deve lidar com estas ações:
Empurrar
Quando o usuário pressiona o controlador rotativo para a direita, o VHAL deve usar a propriedade HW_KEY_INPUT
com os seguintes int32Values
para enviar um evento para o Android:
-
ACTION_DOWN
-
KEYCODE_SYSTEM_NAVIGATION_RIGHT
- Exibição do alvo.
Quando o usuário libera o controlador rotativo, o VHAL deve usar a mesma propriedade e código de chave com ACTION_UP
. Nudges em outras direções devem usar os códigos de chave correspondentes.
Não há códigos de teclas para diagonais, mas o VHAL pode combinar um evento horizontal e vertical para produzir uma diagonal se o hardware suportar diagonais. Por exemplo, empurrar para cima e para a esquerda deve produzir:
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
Em qualquer ordem (e subsequentemente), a liberação do controlador rotativo deve produzir:
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP
O usuário pode empurrar o controlador rotativo em uma direção perpendicular antes de soltá-lo. Por exemplo, o seguinte cenário:
![Direção perpendicular](https://source.android.google.cn/static/devices/automotive/images/rotary_06.png?authuser=7&hl=pt)
Isso deve gerar a seguinte sequência de eventos:
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP
Nenhum evento repetido deve ser gerado enquanto o controlador rotativo é mantido em uma direção.
Girar
Quando o usuário gira o controlador rotativo no sentido horário em um retentor (clique), o VHAL deve usar a propriedade HW_ROTARY_INPUT
com os seguintes int32Values
para enviar um evento para o Android:
-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- Um (1) retentor.
- Exibição do alvo.
O carimbo de data/hora do evento deve ser definido para o tempo decorrido em nanossegundos.
Uma rotação de um (1) detentor no sentido anti-horário deve gerar o mesmo evento, mas com -1 para o número de detentores.
Se ocorrerem vários detentores de rotação na mesma direção em rápida sucessão, o VHAL deve combinar os detentores em um único evento para não sobrecarregar o sistema com eventos. Nesse caso, o carimbo de data/hora do evento deve ser quando ocorreu o primeiro detentor da rotação. Os int32Values
devem incluir o número de nanossegundos entre os detentores consecutivos de rotação.
Por exemplo, a seguinte sequência de rotações:
- No tempo t0, o usuário girou um detentor no sentido anti-horário.
- No tempo t0 + 5 ns, o usuário girou um detentor no sentido anti-horário.
- No tempo t0 + 8 ns, o usuário girou um detentor no sentido anti-horário.
deve gerar este evento:
- Propriedade:
HW_ROTARY_INPUT
- Carimbo de data e hora:
t0
-
int32Values
:-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- -3 (três batentes no sentido anti-horário).
- Exibição do alvo.
- 5 ns entre o primeiro e o segundo detentor.
- 3 ns entre o segundo e o terceiro detentor.
-
Botão central
Quando o usuário pressiona o botão central, o VHAL deve usar a propriedade HW_KEY_INPUT
com os seguintes int32Values
para enviar um evento para o Android:
-
ACTION_DOWN
-
KEYCODE_DPAD_CENTER
- Exibição do alvo.
Quando o usuário libera o controlador rotativo, o VHAL deve usar a mesma propriedade e código de chave com ACTION_UP
.
Não gere eventos repetidos quando o botão central estiver pressionado.
Botão "voltar
Quando o usuário pressiona o botão Voltar, o VHAL deve usar a propriedade HW_KEY_INPUT
com os seguintes int32Values
para enviar um evento para o Android:
-
ACTION_DOWN
-
KEYCODE_BACK
- Exibição do alvo.
Quando o usuário libera o controlador rotativo, o VHAL deve usar a mesma propriedade e código de chave com ACTION_UP
.
Nenhum evento repetido deve ser gerado enquanto o botão central estiver pressionado.
Botão de início
Manuseie o botão Home como faria com o botão Voltar, mas com KEYCODE_HOME
em vez de KEYCODE_BACK
.
Outros botões
Se o controlador rotativo incluir botões adicionais, o VHAL pode lidar com eles, no entanto, o OEM gosta, pois eles não são considerados parte do rotativo da perspectiva do Android. Normalmente, eles são tratados como os botões Voltar e Início, mas com códigos de chave diferentes. Por exemplo, KEYCODE_CALL
ou KEYCODE_MUSIC
.
Configuração de compilação
A navegação rotativa é fornecida por um serviço de acessibilidade chamado RotaryService
. Para incluir este serviço na imagem do sistema do seu dispositivo, adicione a seguinte linha ao seu makefile:
PRODUCT_PACKAGES += CarRotaryController
Você também pode querer incluir os seguintes pacotes nas compilações de depuração:
-
RotaryPlayground
Um aplicativo de referência para rotativo (consulte RotaryPlayground ). -
RotaryIME
Um IME rotativo de demonstração (consulte Editores de método de entrada ). -
CarRotaryImeRRO
A sobreposição paraRotaryIME
.
O serviço rotativo é ativado automaticamente quando o dispositivo é inicializado e quando ocorre uma troca de usuário. Isso garante que o usuário possa usar o controlador rotativo durante a configuração.
Se você usar a mesma compilação para carros com e sem um controlador rotativo, adicione CarRotaryController
conforme mostrado acima para que o código necessário seja incluído na compilação. Para evitar que o serviço rotativo seja habilitado em carros não rotativos, crie um RRO estático para sobrepor o recurso de string rotaryService
em packages/services/Car/service
com uma string vazia. Você usará a mesma compilação, mas terá configurações de produto separadas, para dispositivos rotativos e não rotativos. Apenas este último inclui a sobreposição.
Costumização
Os OEMs podem personalizar a lógica de localização de foco, o destaque de foco e alguns itens adicionais por meio de sobreposições de recursos nos seguintes locais:
- car-ui-library está localizado em
packages/apps/Car/libs/car-ui-lib
-
RotaryService
está localizado empackages/apps/Car/RotaryController
-
Core
está localizado emframeworks/base/core
Histórico de deslocamento
O OEM pode configurar se cada um dos dois tipos de histórico de nudge está habilitado e, em caso afirmativo, o tamanho do cache e a política de expiração. Tudo isso é feito substituindo vários recursos car-ui-library.
Cache do histórico de foco
( Android 11 QPR3, Android 11 Carro, Android 12 )
Esse cache FocusArea
armazena a visualização focada mais recentemente dentro da FocusArea
para que ela possa ser focada ao voltar para a FocusArea
. Esse cache pode ser configurado sobrepondo os seguintes recursos car-ui-library:
-
car_ui_focus_history_cache_type
:- O cache está desabilitado.
- O cache expirará após algum tempo (veja abaixo).
- O cache nunca expirará.
-
car_ui_focus_history_expiration_period_ms
: Quantos milissegundos antes que o cache expire se o tipo de cache for definido como dois (2) (veja acima).
Cache de histórico do FocusArea
( Android 11 QPR3, Android 11 Carro, Android 12 )
Esse cache armazena um histórico de nudges para que o nudge na direção oposta possa retornar o foco para a mesma FocusArea
. Esse cache pode ser configurado sobrepondo os seguintes recursos car-ui-library:
-
car_ui_focus_area_history_cache_type
:- O cache está desabilitado.
- O cache expira após algum tempo (veja abaixo).
- O cache nunca expira.
-
car_ui_focus_area_history_expiration_period_ms
: Quantos milissegundos antes do cache expirar se o tipo de cache for definido como 2 (veja acima). -
car_ui_clear_focus_area_history_when_rotating
: se o cache deve ser anulado quando o usuário gira o controlador.
Rotação
( Android 11 QPR3, Android 11 Carro, Android 12 )
O OEM pode substituir dois recursos inteiros no RotaryService
para especificar se há aceleração, como aceleração do mouse, para rotação:
-
rotation_acceleration_3x_ms
: intervalo de tempo (em milissegundos) usado para decidir se o Google deve acelerar a rotação do controlador para um intervalo de rotação. Se o intervalo entre este batente e o batente de rotação anterior for menor que este valor, será tratado como três batentes de rotação. Defina como 2147483647 para desativar a aceleração 3×. -
rotation_acceleration_2x_ms
: Semelhante arotation_acceleration_3x_ms
. Usado para aceleração 2×. Defina como2147483647
para desativar a aceleração 2×.
A aceleração funciona melhor quando há registros de data e hora individuais para cada detentor de rotação, conforme exigido pelo VHAL. Se estes não estiverem disponíveis, o RotaryService
assume que os detentores de rotação estão espaçados uniformemente.
/** * Property to feed H/W rotary events to android * * int32Values[0] : RotaryInputType identifying which rotary knob rotated * int32Values[1] : number of detents (clicks), positive for clockwise, * negative for counterclockwise * int32Values[2] : target display defined in VehicleDisplay. Events not * tied to specific display must be sent to * VehicleDisplay#MAIN. * int32values[3 .. 3 + abs(number of detents) - 2]: * nanosecond deltas between pairs of consecutive detents, * if the number of detents is > 1 or < -1 * * VehiclePropValue.timestamp: when the rotation occurred. If the number of * detents is > 1 or < -1, this is when the * first detent of rotation occurred. * * @change_mode VehiclePropertyChangeMode:ON_CHANGE * @data_enum RotaryInputType * @access VehiclePropertyAccess:READ */ HW_ROTARY_INPUT = ( 0x0A20 | VehiclePropertyGroup:SYSTEM | VehiclePropertyType:INT32_VEC | VehicleArea:GLOBAL),
Destaque de foco
O OEM pode substituir o destaque de foco padrão na estrutura do Android e vários recursos de destaque de foco em car-ui-library.
Destaque de foco padrão
A estrutura do Android fornece um destaque de foco padrão por meio do atributo selectableItemBackground
. Em Theme.DeviceDefault
, este atributo se refere a item_background.xml
no Core
. O OEM pode sobrepor item_background.xml
para alterar o desenhável de destaque de foco padrão.
Esse drawable normalmente deve ser um StateListDrawable
, que ajusta o plano de fundo com base em diferentes combinações de estados, incluindo android:state_focused
e android:state_pressed
. Quando o usuário usa o controlador rotativo para focar uma visualização, android:state_focused
será true
, mas android:state_pressed
será false
. Se o usuário pressionar o botão central no controlador rotativo, android:state_focused
e android:state_pressed
serão true
enquanto o usuário mantiver o botão pressionado. Quando o usuário soltar o botão, apenas android:state_focused
permanecerá true
.
car-ui-library usa um tema derivado de Theme.DeviceDefault
. Como resultado, essa sobreposição afeta aplicativos que usam essa biblioteca e aplicativos que usam qualquer tema derivado de Theme.DeviceDefault
. Ele não afetará aplicativos que usam um tema não relacionado, como Theme.Material
.
Recursos de destaque de foco em car-ui-library
O OEM pode substituir vários recursos car-ui-library para controlar a aparência do destaque de foco em exibições com um destaque de foco não retangular (como redondo ou em forma de pílula) e em aplicativos que usam um tema que não deriva de Theme.DeviceDefault
. Esses recursos devem ser sobrepostos para que o destaque de foco seja consistente com o desenhável de destaque de foco padrão .
( Android 11 QPR3, Android 11 Carro, Android 12 )
Os seguintes recursos são usados para indicar quando uma visualização está focada, mas não pressionada:
-
car_ui_rotary_focus_fill_color
: Cor de preenchimento. -
car_ui_rotary_focus_stroke_color
: Cor do contorno. -
car_ui_rotary_focus_stroke_width
: Espessura do contorno.
( Android 11 QPR3, Android 11 Carro, Android 12 )
Os seguintes recursos são usados para indicar quando uma visualização é focada e pressionada:
-
car_ui_rotary_focus_pressed_fill_color
: Cor de preenchimento. -
car_ui_rotary_focus_pressed_stroke_color
: Cor do contorno. -
car_ui_rotary_focus_pressed_stroke_width
: Espessura do contorno.
Às vezes, um botão recebe uma cor de fundo sólida para chamar a atenção do usuário, como no exemplo mostrado. Isso pode dificultar a visualização do destaque do foco.
![Botão com fundo sólido](https://source.android.google.cn/static/devices/automotive/images/rotary_05.png?authuser=7&hl=pt)
- ( Android 11 QPR3, Android 11 Carro, Android 12 )
car_ui_rotary_focus_fill_secondary_color
car_ui_rotary_focus_stroke_secondary_color
- ( Android12 )
car_ui_rotary_focus_pressed_fill_secondary_color
car_ui_rotary_focus_pressed_stroke_secondary_color
Qualquer uma das cores pode ser transparente e qualquer dimensão pode ser zero se, por exemplo, você quiser apenas um preenchimento ou apenas um contorno.
Destaque da área de foco
( Android 11 QPR3, Android 11 Carro, Android 12 )
FocusArea
pode desenhar dois tipos de destaque quando um de seus descendentes está focado. Ambos podem ser usados em conjunto, se desejado. Esse recurso é desabilitado por padrão no AOSP, mas pode ser habilitado substituindo os recursos car-ui-library:
-
car_ui_enable_focus_area_foreground_highlight
: Desenhe um destaque em cima doFocusArea
e seus descendentes. No AOSP, este drawable é um contorno em torno doFocusArea
. Os OEMs podem substituir o drawablecar_ui_focus_area_foreground_highlight
. -
car_ui_enable_focus_area_background_highlight
: Desenhe um destaque em cima doFocusArea
mas atrás de seus descendentes. No AOSP, este drawable é um preenchimento sólido. Os OEMs podem substituir o drawablecar_ui_focus_area_background_highlight
.
Editores de método de entrada
Editores de método de entrada (IME) são métodos de entrada. Por exemplo, um teclado na tela.
( Android 11 QPR3, Android 11 Carro, Android 12 )
O OEM deve sobrepor o recurso de string default_touch_input_method
no RotaryService
para especificar o ComponentName
do IME baseado em toque. Por exemplo, se o OEM usar o IME fornecido com o Android Automotive, ele deverá especificar com.google.android.apps.automotive.inputmethod/.InputMethodService
.
( Android 11 QPR3, Android 11 Carro, Android 12 )
Se o OEM criou um IME especificamente para rotativo, ele deve especificar seu ComponentName
no recurso rotary_input_method
. Se esse recurso for sobreposto, o IME especificado será usado sempre que o usuário estiver interagindo com a unidade principal por meio do botão de deslocamento, rotação e central do controlador rotativo. Quando o usuário tocar na tela, o IME anterior será usado. O botão Voltar (e outros botões no controlador giratório) não têm efeito na seleção de IME. Se esse recurso não for sobreposto, não ocorrerá troca de IME. O Carboard não é compatível com rotação, portanto, o usuário não pode inserir texto por meio do controlador giratório se o OEM não tiver fornecido um IME giratório.
RotaryIME
é um IME rotativo de demonstração. Embora básico, é suficiente experimentar a troca automática de IME descrita acima. O código fonte do RotaryIME
pode ser encontrado em packages/apps/Car/tests/RotaryIME/
.
Empurrões fora da tela
Por padrão, quando o usuário tenta afastar a borda da tela, nada acontece. O OEM pode configurar o que deve ocorrer para cada uma das quatro direções especificando qualquer combinação de:
- Uma ação global definida por
AccessibilityService
. Por exemplo,GLOBAL_ACTION_BACK
. - Um código de chave, como
KEYCODE_BACK
. - Uma intenção de iniciar uma atividade representada como um URL.
( Android 11 QPR3, Android 11 Carro, Android 12 )
Eles são especificados sobrepondo os seguintes recursos de array no RotaryService
:
-
off_screen_nudge_global_actions
: Matriz de ações globais a serem executadas quando o usuário empurra para cima, para baixo, para a esquerda ou para a direita na borda da tela. Nenhuma ação global é executada se o elemento relevante desta matriz for -1. -
off_screen_nudge_key_codes
: matriz de códigos-chave de eventos de clique para injetar quando o usuário empurra para cima, para baixo, para a esquerda ou para a direita na borda da tela. Nenhum evento é injetado se o elemento relevante deste array for 0 (KEYCODE_UNKNOWN
). -
off_screen_nudge_intents
: matriz de intents para iniciar uma atividade quando o usuário empurra para cima, para baixo, para a esquerda ou para a direita na borda da tela. Nenhuma atividade é iniciada se o elemento relevante desta matriz estiver vazio.
Outras configurações
Você deve sobrepor os seguintes recursos do RotaryService
:
- ( Android 11 QPR3, Android 11 Carro, Android 12 )
config_showHeadsUpNotificationOnBottom
: valor booleano para representar se as notificações de alerta devem ser mostradas na parte inferior e não na parte superior. Deve ter o mesmo valor que o recurso booleanoconfig_showHeadsUpNotificationOnBottom
emframeworks/base/packages/CarSystemUI/res/values/config.xml
- ( Android 11 QPR3, Android 11 Carro, Android 12 )
notification_headsup_card_margin_horizontal
: Margem esquerda e direita da janela de notificação de heads-up. Isso deve ter o mesmo valor que o recurso de dimennotification_headsup_card_margin_horizontal
empackages/apps/Car/Notification/res/values/dimens.xml
- ( Android12 )
excluded_application_overlay_window_titles
: uma matriz de títulos de janelas que não devem ser consideradas janelas de sobreposição. Isso deve incluir títulos de janelas de aplicativos que representamTaskViews
ouTaskDisplayAreas
. Por padrão, esta lista contém apenas "Mapas".
Você pode sobrepor o seguinte recurso RotaryService
:
- ( Android 11 QPR3, Android 11 Carro, Android 12 )
long_press_ms
: valor inteiro para representar quantos milissegundos o botão central deve ser pressionado para acionar um pressionamento longo. Zero indica que o tempo limite de pressionamento longo padrão do sistema deve ser usado. Este é o valor padrão.