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 iniciador fornecido pelo OEM, consulte Car UI Library (car-ui-library) .
VHAL
Um controlador rotativo suporta as seguintes ações:
- Deslocar 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 obter a documentação sobre as propriedades do sistema e int32Values
correspondentes.
O VHAL deve lidar com estas ações:
cutucar
Quando o usuário pressiona o controlador giratório 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 de alvo.
Quando o usuário libera o controlador rotativo, o VHAL deve usar a mesma propriedade e código-chave com ACTION_UP
. Nudges em outras direções devem usar os códigos-chave correspondentes.
Não há códigos-chave para diagonais, mas o VHAL pode combinar um evento horizontal e vertical para produzir uma diagonal se o hardware suportar diagonais. Por exemplo, deslocar 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 subseqüentemente), 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 liberá-lo. Por exemplo, o seguinte cenário:
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 giratório é mantido em uma direção.
Girar
Quando o usuário gira o controlador rotativo em um detento (clique) no sentido horário, 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 de alvo.
O registro de data e hora do evento deve ser definido como o tempo decorrido em nanossegundos.
Uma (1) rotação anti-horária de um (1) detentor deve gerar o mesmo evento, mas com -1 para o número de detentores.
Se vários detentores de rotação na mesma direção ocorrerem 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 timestamp do evento deve ser quando ocorreu o primeiro detentor de rotação. Os int32Values
devem incluir o número de nanossegundos entre 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/hora:
t0
-
int32Values
:-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- -3 (três detentores no sentido anti-horário).
- Exibição de alvo.
- 5 ns entre a primeira e a segunda retenção.
- 3 ns entre a segunda e a terceira retenção.
-
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 de alvo.
Quando o usuário libera o controlador rotativo, o VHAL deve usar a mesma propriedade e código-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 de alvo.
Quando o usuário libera o controlador rotativo, o VHAL deve usar a mesma propriedade e código-chave com ACTION_UP
.
Nenhum evento repetido deve ser gerado enquanto o botão central estiver pressionado.
botão home
Manipule 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 quaisquer botões adicionais, o VHAL pode manipulá-los da maneira que o OEM quiser, 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 acesso 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 em compilações de depuração:
-
RotaryPlayground
Um aplicativo de referência para rotary (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 inicializa 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 ativado 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 construção, mas terá configurações de produto separadas para dispositivos rotativos e não rotativos. Apenas o ú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
Deslocar histórico
O OEM pode configurar se cada um dos dois tipos de histórico de nudge está habilitado ou não 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 por FocusArea
armazena a exibiçã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).
- Cache nunca irá expirar.
-
car_ui_focus_history_expiration_period_ms
: Quantos milissegundos antes do cache expirar se o tipo de cache for definido como dois (2) (veja acima).
Cache do histórico 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).
- 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 detentor de rotação. Se o intervalo entre este detentor e o anterior detentor de rotação for menor que este valor, ele será tratado como três detentores de rotação. Defina como 2147483647 para desabilitar a aceleração 3×. -
rotation_acceleration_2x_ms
: Semelhante arotation_acceleration_3x_ms
. Usado para aceleração 2×. Defina como2147483647
para desabilitar a aceleração 2×.
A aceleração funciona melhor quando há timestamps individuais para cada detentor de rotação, conforme exigido pelo VHAL. Se eles 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 do 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
, esse atributo refere-se item_background.xml
no Core
. O OEM pode sobrepor item_background.xml
para alterar o drawable 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 giratório para focalizar 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 giratório, 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
. Isso não afetará aplicativos que usam um tema não relacionado, como Theme.Material
.
Concentre-se em destacar recursos na biblioteca de interface do usuário do carro
O OEM pode substituir vários recursos car-ui-library para controlar a aparência do destaque do foco em exibições com 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 do foco seja consistente com o drawable de destaque do foco padrão .
( Android 11 QPR3, Android 11 Carro, Android 12 )
Os seguintes recursos são usados para indicar quando uma vista 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 visã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 realce do foco.
Nessa situação, o desenvolvedor pode especificar um destaque de foco personalizado usando cores secundárias :- ( Android 11 QPR3, Android 11 Carro, Android 12 )
car_ui_rotary_focus_fill_secondary_color
car_ui_rotary_focus_stroke_secondary_color
- ( Andróide 12 )
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 FocusArea
( Android 11 QPR3, Android 11 Carro, Android 12 )
FocusArea
pode desenhar dois tipos de realce quando um de seus descendentes é focado. Ambos podem ser usados em conjunto, se desejado. Esse recurso está desativado por padrão no AOSP, mas pode ser ativado substituindo os recursos car-ui-library:
-
car_ui_enable_focus_area_foreground_highlight
: Desenhe um destaque no topo daFocusArea
e seus descendentes. No AOSP, esse desenhável é um contorno ao redor daFocusArea
. Os OEMs podem substituir o desenhávelcar_ui_focus_area_foreground_highlight
. -
car_ui_enable_focus_area_background_highlight
: Desenhe um destaque no topo daFocusArea
, mas atrás de seus descendentes. No AOSP, esse drawable é um preenchimento sólido. Os OEMs podem substituir o desenhávelcar_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 rotary, 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 central, rotação e deslocamento do controlador giratório. 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 tem efeito na seleção do IME. Se esse recurso não for sobreposto, não ocorrerá nenhuma alternância de IME. O Carboard não oferece suporte ao rotativo, portanto, o usuário não pode inserir texto por meio do controlador rotativo se o OEM não tiver fornecido um IME rotativo.
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 sair da 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-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 pela sobreposição dos seguintes recursos de matriz no RotaryService
:
-
off_screen_nudge_global_actions
: Matriz de ações globais a serem executadas quando o usuário move para cima, para baixo, para a esquerda ou para a direita fora da borda da tela. Nenhuma ação global é executada se o elemento relevante dessa matriz for -1. -
off_screen_nudge_key_codes
: matriz de códigos de teclas de eventos de clique para injetar quando o usuário move para cima, para baixo, para a esquerda ou para a direita fora da borda da tela. Nenhum evento é injetado se o elemento relevante desta matriz for 0 (KEYCODE_UNKNOWN
). -
off_screen_nudge_intents
: matriz de intents para iniciar uma atividade quando o usuário move para cima, para baixo, para a esquerda ou para a direita fora da borda da tela. Nenhuma atividade é iniciada se o elemento relevante dessa matriz estiver vazio.
Outras configurações
Você deve sobrepor os seguintes recursos 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 em oposição à 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 para janela de notificação heads-up. Isso deve ter o mesmo valor que o recursonotification_headsup_card_margin_horizontal
dimen empackages/apps/Car/Notification/res/values/dimens.xml
- ( Andróide 12 )
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.