Guia de integração para OEMs

Esta página 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:

  • Deslize 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:

Cutucar

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 ao Android:

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

Quando o usuário libera o controlador rotativo, o VHAL deve usar a mesma propriedade e código-chave com ACTION_UP . Os empurrões em outras direções devem usar os códigos-chave correspondentes.

Não existem 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-se 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
Figura 1. Direção perpendicular

Isso deve 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 repetido deve ser gerado enquanto o controlador rotativo for mantido em uma direção.

Girar

Quando o usuário gira o controlador rotativo no sentido horário em uma posição (clique), o VHAL deve usar a propriedade HW_ROTARY_INPUT com os seguintes int32Values ​​para enviar um evento ao Android:

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

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

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

Se múltiplos detentores de rotação na mesma direção ocorrerem em rápida sucessão, o VHAL deverá combinar os detentores em um único evento para não sobrecarregar o sistema com eventos. Neste caso, o carimbo de data/hora do evento deve ser quando ocorreu o primeiro detentor de rotação. O int32Values ​​deve incluir o número de nanossegundos entre detenções consecutivas 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 :
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (três detentores no sentido anti-horário).
    3. Exibição de destino.
    4. 5 ns entre a primeira e a segunda retenção.
    5. 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 ao Android:

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

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 for 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 ao Android:

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

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 inicial

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 poderá lidar com eles da maneira que o OEM desejar, 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 incluir os seguintes pacotes em compilações de depuração:

O serviço rotativo é habilitado automaticamente quando o dispositivo é inicializado e quando ocorre uma troca de usuário. Isto 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 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 construçã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á localizada em packages/apps/Car/libs/car-ui-lib
  • RotaryService está localizado em packages/apps/Car/RotaryController
  • Core está localizado em frameworks/base/core

História de cutucada

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 da biblioteca car-ui.

Cache de histórico de foco

( Android 11 QPR3, carro Android 11, Android 12 )
Esse cache por FocusArea armazena a visualização focada mais recentemente dentro do FocusArea para que possa ser focada ao retornar ao FocusArea . Esse cache pode ser configurado sobrepondo os seguintes recursos da car-ui-library:

  • car_ui_focus_history_cache_type :
    1. O cache está desativado.
    2. O cache irá expirar após algum tempo (veja abaixo).
    3. O cache nunca expirará.
  • car_ui_focus_history_expiration_period_ms : Quantos milissegundos antes que o cache expire se o tipo de cache estiver definido como dois (2) (veja acima).

Cache de histórico FocusArea

( Android 11 QPR3, carro Android 11, Android 12 )
Esse cache armazena um histórico de deslocamentos para que os deslocamentos na direção oposta possam retornar o foco para o mesmo FocusArea . Esse cache pode ser configurado sobrepondo os seguintes recursos da car-ui-library:

  • 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 que o cache expire se o tipo de cache estiver definido como 2 (veja acima).
  • car_ui_clear_focus_area_history_when_rotating : se deve anular o cache quando o usuário gira o controlador.

Rotação

( Android 11 QPR3, carro Android 11, 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 limite 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 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 detentor de rotação, conforme exigido pelo VHAL. Se 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 Android e vários recursos de destaque de foco na car-ui-library.

Destaque de foco padrão

A estrutura Android fornece um destaque de foco padrão por meio do atributo selectableItemBackground . Em Theme.DeviceDefault , este atributo refere-se a item_background.xml em 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 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 mantém 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 esta 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 .

Foco em recursos de destaque na car-ui-library

O OEM pode substituir vários recursos da car-ui-library para controlar a aparência do realce de foco em visualizações com realce de foco não retangular (como redondo ou em forma de pílula) e em aplicativos que usam um tema que não deriva do 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, carro Android 11, 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, carro Android 11, Android 12 )
Os seguintes recursos são usados ​​para indicar quando uma visualização está 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.

Botão com fundo sólido
Figura 2. Botão com fundo sólido

Nessa situação, o desenvolvedor pode especificar um realce de foco personalizado usando cores secundárias :
  • ( Android 11 QPR3, carro Android 11, 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ê quiser apenas um preenchimento ou apenas um contorno.

Destaque FocusArea

( Android 11 QPR3, carro Android 11, Android 12 )
FocusArea pode desenhar dois tipos de destaque quando um de seus descendentes está em foco. Ambos podem ser usados ​​em conjunto, se desejado. Este recurso está 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 no topo da FocusArea e seus descendentes. No AOSP, esse drawable é um contorno em torno do FocusArea . Os OEMs podem substituir o drawable car_ui_focus_area_foreground_highlight .
  • car_ui_enable_focus_area_background_highlight : desenhe um destaque no topo da FocusArea , mas atrás de seus descendentes. No AOSP, esse drawable é um preenchimento sólido. Os OEMs podem substituir o drawable car_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, carro Android 11, 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, carro Android 11, Android 12 )
Se o OEM tiver criado um IME especificamente para rotativo, ele deverá 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 deslocamento, da rotação e do botão central do controlador rotativo. Quando o usuário tocar na tela, o IME anterior será utilizado. O botão Voltar (e outros botões no controlador rotativo) não têm efeito na seleção do IME. Se esse recurso não for sobreposto, nenhuma alternância de IME ocorrerá. O Carboard não suporta rotação, portanto o usuário não poderá 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/ .

Cutucadas 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:

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

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

  • off_screen_nudge_global_actions : matriz de ações globais a serem executadas quando o usuário desliza para cima, para baixo, para a esquerda ou para a direita na borda da tela. Nenhuma ação global será executada se o elemento relevante desta matriz for -1.
  • off_screen_nudge_key_codes : matriz de códigos-chave de eventos de clique a serem injetados quando o usuário move para cima, para baixo, para a esquerda ou para a direita na borda da tela. Nenhum evento será injetado se o elemento relevante desta matriz for 0 ( KEYCODE_UNKNOWN ).
  • off_screen_nudge_intents : matriz de intenções para iniciar uma atividade quando o usuário desliza 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 RotaryService :

  • ( Android 11 QPR3, carro Android 11, 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 booleano config_showHeadsUpNotificationOnBottom em frameworks/base/packages/CarSystemUI/res/values/config.xml
  • ( Android 11 QPR3, carro Android 11, Android 12 )
    notification_headsup_card_margin_horizontal : Margens esquerda e direita para janela de notificação de alerta. Deve ter o mesmo valor que o recurso de dimensão notification_headsup_card_margin_horizontal 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 aplicativos que representem TaskViews ou TaskDisplayAreas . Por padrão, esta lista contém apenas “Mapas”.

Você pode sobrepor o seguinte recurso RotaryService :

  • ( Android 11 QPR3, carro Android 11, Android 12 )
    long_press_ms : valor inteiro para representar quantos milissegundos o botão central deve ser pressionado para acionar um toque longo. Zero indica que o tempo limite padrão do sistema para pressionar longamente deve ser usado. Este é o valor padrão.