Guia de integração para OEMs

Esta página descreve como processar entradas por seletor giratório na VHAL, configurar seu build para incluir o serviço de seletor giratório e como personalizar essa experiência em todos os apps. Para apps OEM pré-instalados, como um inicializador fornecido pelo OEM, consulte Biblioteca Car UI (car-ui-library).

VHAL

Um controle giratório é compatível com 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 home.
  • Pressione outros botões, como "Telefone" e "Mídia".

Consulte hardware/interfaces/automotive/vehicle/2.0/types.hal para ver a documentação sobre as propriedades do sistema e o int32Values correspondente.

A VHAL precisa lidar com estas ações:

Piano

Quando o usuário empurra o controle giratório para a direita, a VHAL deve usar o HW_KEY_INPUT com o seguinte int32Values para enviar uma para o Android:

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Exibição de destino.

Quando o usuário solta o controle giratório, a VHAL deve usar a mesma propriedade e com ACTION_UP. Deslocamentos em outras direções devem usar o os códigos de tecla correspondentes.

Não há códigos de tecla para diagonais, mas a VHAL pode combinar uma combinação horizontal e vertical para produzir uma diagonal se o hardware oferecer suporte a diagonais. Por exemplo, chamar e à 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 posteriormente), soltar o controle giratório 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 controle giratório em uma direção perpendicular antes de liberá-lo. Por exemplo, o cenário a seguir:

Direção perpendicular
Figura 1. Direção perpendicular

Isso vai gerar a seguinte sequência de eventos:

  1. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  2. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
  3. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  4. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

Nenhum evento repeat pode ser gerado enquanto o controle giratório estiver pressionado em uma direção.

Rotação

Quando o usuário gira o controle giratório no sentido horário em um ponto (clique), a VHAL precisa usar a propriedade HW_ROTARY_INPUT com o seguinte int32Values para enviar um evento ao Android:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Um (1) limite.
  3. Exibição de destino.

O carimbo de data/hora do evento precisa ser definido como o tempo decorrido em nanossegundos.

Uma (1) rotação no sentido anti-horário deve gerar o mesmo evento, mas com -1 para o número de retenções.

Se várias barreiras de rotação na mesma direção ocorrerem em rápida sucessão, a VHAL deve combinar os bloqueios em um único evento para não sobrecarregar o sistema com eventos. Nesse caso, o carimbo de data/hora do evento deve ser o momento em que ocorreu a primeira retenção da rotação. int32Values precisa incluir o número de nanossegundos entre os dentes consecutivos de rotação.

Por exemplo, a seguinte sequência de rotações:

  • No tempo t0, o usuário girou um limite em sentido anti-horário.
  • No tempo t0 + 5 ns, o usuário girou um ponto no sentido anti-horário.
  • No tempo t0 + 8 ns, o usuário girou um ponto no sentido anti-horário.

deve gerar este evento:

  • Propriedade: HW_ROTARY_INPUT
  • Carimbo de data/hora: t0
  • int32Values:
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (três pontos no sentido anti-horário).
    3. Exibição de destino.
    4. 5 ns entre o primeiro e o segundo recuo.
    5. 3 ns entre o segundo e o terceiro ponto de contenção.

Botão central

Quando o usuário pressiona o botão central, a VHAL precisa usar o HW_KEY_INPUT com o seguinte int32Values para enviar um evento ao Android:

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Exibição de destino.

Quando o usuário solta o controle giratório, a VHAL precisa usar a mesma propriedade e o código de tecla com ACTION_UP.

Não gere eventos repeat quando o botão central for pressionado.

Botão "Voltar"

Quando o usuário pressiona o botão "Voltar", a VHAL precisa usar o HW_KEY_INPUT. com o seguinte int32Values para enviar um evento ao Android:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Exibição de destino.

Quando o usuário solta o controle giratório, a VHAL precisa usar a mesma propriedade e o código de tecla com ACTION_UP.

Nenhum evento repeat deve ser gerado enquanto o botão central estiver pressionado.

Botão "Início"

Gerencie o botão home como faria com o botão "Voltar", mas com KEYCODE_HOME. de KEYCODE_BACK.

Outros botões

Se o controle giratório incluir botões adicionais, a VHAL poderá processá-los. o OEM gosta, porque eles não são considerados parte do seletor giratório do ponto de vista do Android. Normalmente, eles são tratados da mesma forma que os botões "Voltar" e "Página inicial", mas com códigos de tecla diferentes. Por exemplo, KEYCODE_CALL ou KEYCODE_MUSIC.

Configuração do build

A navegação por seletor giratório é 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

Também é possível incluir os seguintes pacotes em builds de depuração:

  • RotaryPlayground Um app de referência para o seletor giratório (consulte RotaryPlayground).
  • RotaryIME Um IME giratório de demonstração (consulte Editores de método de entrada).
  • CarRotaryImeRRO A sobreposição para RotaryIME.

O serviço por seletor giratório é ativado automaticamente quando o dispositivo é inicializado e quando um usuário quando a mudança acontece. Isso garante que o usuário possa usar o controle giratório durante a configuração.

Se você usa a mesma versão para carros com e sem controle giratório, Adicione CarRotaryController, conforme mostrado acima, para que o código necessário seja incluído. no build. Para evitar que o serviço giratório seja ativado em carros não giratórios, crie um a RRO estática para sobrepor o recurso de string rotaryService packages/services/Car/service com uma string vazia. Você vai usar o mesmo build, mas têm configurações de produto separadas, para dispositivos giratórios e não giratórios. Apenas o último caso inclui a sobreposição.

Personalização

Os OEMs podem personalizar a lógica de localização de foco, o destaque e alguns outros itens usando sobreposições de recursos nos seguintes locais:

  • car-ui-library está localizada em packages/apps/Car/libs/car-ui-lib
  • RotaryService está localizado em packages/apps/Car/RotaryController
  • Core está localizado em frameworks/base/core

Deslocar histórico

O OEM pode configurar se cada um dos dois tipos de histórico de alertas está ativado e, em caso afirmativo, o tamanho do cache e a política de expiração. Isso é feito substituindo-se de várias bibliotecas do Google Cloud.

Focar o cache do histórico

(Android 11 QPR3, Android 11 Car, Android 12)
Esse cache por FocusArea armazena a visualização mais recentemente focada no FocusArea para que ele possa ser focado ao voltar para o FocusArea. Esse cache pode ser configurado sobrepondo os seguintes recursos da biblioteca car-ui-library:

  • car_ui_focus_history_cache_type:
    1. O cache está desativado.
    2. O cache expira após algum tempo (veja abaixo).
    3. O cache nunca expira.
  • car_ui_focus_history_expiration_period_ms: quantos milissegundos antes do evento cache vai expirar se o tipo de cache for definido como dois (2) (veja acima).

Cache do histórico do FocusArea

(Android 11 QPR3, Android 11 Car, Android 12)
Esse cache armazena um histórico de alertas para que o deslocamento na direção oposta possa voltar o foco para o mesmo FocusArea. Esse cache pode ser configurado sobrepondo seguintes recursos da biblioteca car-ui:

  • car_ui_focus_area_history_cache_type:
    1. O cache está desativado.
    2. O cache expira após algum tempo (veja abaixo).
    3. O cache nunca expira.
  • car_ui_focus_area_history_expiration_period_ms: quantos milissegundos antes o cache vai expirar se o tipo de cache for definido como 2 (veja acima).
  • car_ui_clear_focus_area_history_when_rotating: se o cache será anulado. quando o usuário gira o controle.

Rotação

(Android 11 QPR3, Android 11 Car, Android 12)
O OEM pode substituir dois recursos de números inteiros no RotaryService para especificar se há aceleração para rotação, como aceleração do mouse:

  • rotation_acceleration_3x_ms: intervalo de tempo (em milissegundos) usado para decidir se o Google deve acelerar a rotação do controlador para um período de rotação. Se o é menor que esse valor, ele será tratado como três perímetros de rotação. Defina como 2147483647 para desativar 3× e aceleração.
  • rotation_acceleration_2x_ms: semelhante a rotation_acceleration_3x_ms. Usado para aceleração 2×. Defina como 2147483647 para desativar a aceleração 2×.

A aceleração funciona melhor quando há carimbos de data/hora individuais para cada retenção de a rotação de chaves, obrigatório pela VHAL. Se elas não estiverem disponíveis, o RotaryService vai presumir que as barreiras de são espaçadas 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),

Focar o destaque

O OEM pode substituir o destaque de foco padrão no framework do Android e vários recursos de destaque de foco em car-ui-library.

Destaque de foco padrão

O framework do Android fornece um destaque de foco padrão pelo atributo selectableItemBackground: Em Theme.DeviceDefault, isso refere-se a item_background.xml em Core. O OEM pode sobrepor item_background.xml para mudar o drawable de destaque de foco padrão.

Esse drawable precisa 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 controle giratório 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 controle giratório, tanto android:state_focused quanto O valor de android:state_pressed será true enquanto o usuário mantiver o botão pressionado. Quando o usuário soltar o botão, apenas android:state_focused permanece true.

O car-ui-library usa um tema derivado de Theme.DeviceDefault. Como resultado, Essa sobreposição afeta os apps que usam essa biblioteca e os que usam qualquer tema derivado Theme.DeviceDefault: Isso não vai afetar apps que usam um tema não relacionado, como Theme.Material.

Focar os recursos de destaque na biblioteca car-ui-library

O OEM pode substituir vários recursos da biblioteca da interface do carro para controlar a forma como o foco destaca observa as visualizações com um destaque não retangular (como redondo ou em forma de pílula) e em Apps que usam um tema não derivado de Theme.DeviceDefault. Esses os recursos devem ser sobrepostos para que o destaque do foco seja consistente com o drawable de destaque de foco padrão.

(Android 11 QPR3, Android 11 Car, Android 12)
Os recursos a seguir são usados para indicar quando uma visualização está em foco, 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 Car, Android 12)
Os recursos a seguir são usados para indicar quando uma visualização está em foco 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 plano de fundo sólido
Figura 2. Botão com fundo sólido

Nessa situação, o desenvolvedor pode especificar um destaque de foco personalizado usando cores secundárias:
  • (Android 11 QPR3, Android 11 Car, Android 12)
    car_ui_rotary_focus_fill_secondary_color (
    ) car_ui_rotary_focus_stroke_secondary_color
  • (Android 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ê queria apenas um preenchimento ou apenas um contorno.

Destaque da área de foco

(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea pode desenhar dois tipos de destaque quando um dos descendentes está focada. Se preferir, é possível usar ambos em conjunto. Esse recurso fica desativado por padrão no AOSP, mas pode ser ativado substituindo os recursos da biblioteca da interface do carro:

  • car_ui_enable_focus_area_foreground_highlight: desenhe um destaque em cima de a FocusArea e os descendentes dela. No AOSP, esse drawable é um contorno ao redor da FocusArea. Os OEMs podem substituir Drawable car_ui_focus_area_foreground_highlight.
  • car_ui_enable_focus_area_background_highlight: desenhe um destaque na parte superior do FocusArea, mas atrás dos descendentes. No AOSP, esse drawable é um preenchimento sólido. Os OEMs podem substituir o drawable car_ui_focus_area_background_highlight.

Editores do método de entrada

Os Editores de método de entrada (IME, na sigla em inglês) são métodos de entrada. Por exemplo, um teclado na tela.

(Android 11 QPR3, Android 11 Car, Android 12)
O OEM precisa sobrepor o recurso de string default_touch_input_method no objeto RotaryService para especificar o ComponentName do IME baseado em toque. Por exemplo, se o OEM usar o IME fornecido com o Android Automotive, ele deve especificar com.google.android.apps.automotive.inputmethod/.InputMethodService:

(Android 11 QPR3, Android 11 Car, Android 12)
Se o OEM tiver criado um IME especificamente para o seletor giratório, ele deverá especificar o ComponentName no recurso rotary_input_method. Se este recurso for sobreposto, o IME especificado será usado sempre que o usuário estiver interagindo com a unidade principal por meio do movimento, da rotação e do botão central do controle giratório. Quando o usuário toca tela, o IME anterior será usado. O botão "Voltar" (e outros botões do ) não afetam a seleção do IME. Se esse recurso não for sobreposto, não haverá troca de IME de segurança. O painel não é compatível com o seletor giratório, então o usuário não pode inserir texto nele se o OEM não tiver fornecido um IME giratório.

RotaryIME é um IME giratório de demonstração. Embora seja básico, é suficiente teste a troca automática do IME descrita acima. O código-fonte de RotaryIME podem ser encontrados em packages/apps/Car/tests/RotaryIME/.

Alerta fora da tela

Por padrão, quando o usuário tenta desviar da borda da tela, nada acontece. O OEM pode configurar o que deve ocorrer para cada uma das quatro direções especificando combinação de:

  1. Uma ação global definida por AccessibilityService. Por exemplo, GLOBAL_ACTION_BACK.
  2. Um código de tecla, como KEYCODE_BACK.
  3. Uma intent para iniciar uma atividade representada como um URL.

(Android 11 QPR3, Android 11 Car, Android 12)
Eles são especificados sobrepondo os seguintes recursos de matriz na RotaryService:

  • off_screen_nudge_global_actions: matriz de ações globais a serem executadas quando o usuário desvia a borda da tela para cima, para baixo, para a esquerda ou para a direita. Nenhuma ação global é executada se o elemento relevante dessa matriz for -1.
  • off_screen_nudge_key_codes: matriz de códigos de chave dos eventos de clique a serem injetados quando o usuário desvia da borda da tela para cima, para baixo, para a esquerda ou para a direita. Nenhum evento é injetado se o elemento relevante dessa matriz for 0 (KEYCODE_UNKNOWN).
  • off_screen_nudge_intents: matriz de intents para iniciar uma atividade quando o usuário desvia a borda da tela para cima, para baixo, para a esquerda ou para a direita. Nenhuma atividade é será iniciado se o elemento relevante dessa matriz estiver vazio.

Outras configurações

Você precisa sobrepor os seguintes recursos RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    config_showHeadsUpNotificationOnBottom: valor booleano que representa se as notificações de alerta devem ser exibidas na parte inferior, não na parte superior. Isso deve têm o mesmo valor de config_showHeadsUpNotificationOnBottom; Recurso booleano em frameworks/base/packages/CarSystemUI/res/values/config.xml
  • (Android 11 QPR3, Android 11 Car, Android 12)
    notification_headsup_card_margin_horizontal: margens esquerda e direita de janela de notificação de alerta. Precisa ter o mesmo valor que o notification_headsup_card_margin_horizontal recurso de dimensão em packages/apps/Car/Notification/res/values/dimens.xml
  • (Android 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 apps que representam TaskViews ou TaskDisplayAreas. Por padrão, essa lista contém apenas "Maps".

É possível sobrepor o seguinte recurso RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    long_press_ms: valor inteiro que representa quantos milissegundos o Mantenha o botão central pressionado para acionar um pressionamento longo. Zero indica que o sistema tempo limite padrão de pressionamento longo. Esse é o valor padrão.