Guía de integración para OEM

Esta página describe cómo procesar entradas rotativas en VHAL, configurar su compilación para incluir el servicio rotativo y cómo personalizar la experiencia rotativa en todas las aplicaciones. Para aplicaciones OEM preinstaladas, como un iniciador proporcionado por OEM, consulte Biblioteca de UI del automóvil (car-ui-library) .

VHAL

Un controlador giratorio admite las siguientes acciones:

  • Empuje hacia arriba, abajo, izquierda y derecha.
  • Gire en el sentido de las agujas del reloj y en el sentido contrario a las agujas del reloj.
  • Presione el botón central.
  • Presiona el botón de atrás.
  • Presione el botón Inicio.
  • Presione otros botones, como Teléfono y Medios.

Consulte hardware/interfaces/automotive/vehicle/2.0/types.hal para obtener documentación sobre las propiedades del sistema y int32Values ​​correspondientes.

El VHAL debería encargarse de estas acciones:

Empujar

Cuando el usuario empuja el controlador giratorio hacia la derecha, VHAL debe usar la propiedad HW_KEY_INPUT con los siguientes int32Values ​​para enviar un evento a Android:

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Visualización de objetivos.

Cuando el usuario suelta el controlador giratorio, el VHAL debe usar la misma propiedad y código clave con ACTION_UP . Los empujones en otras direcciones deben utilizar los códigos clave correspondientes.

No hay códigos clave para diagonales, pero VHAL puede combinar un evento horizontal y vertical para producir una diagonal si el hardware admite diagonales. Por ejemplo, empujar hacia arriba y hacia la izquierda debería producir:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN

En cualquier orden (y posteriormente), al soltar el controlador giratorio se debería producir:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

El usuario puede empujar el controlador giratorio en dirección perpendicular antes de soltarlo. Por ejemplo, el siguiente escenario:

dirección perpendicular
Figura 1. Dirección perpendicular

Esto debería generar la siguiente secuencia 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

No se deben generar eventos repetidos mientras el controlador giratorio se mantiene en una dirección.

Girar

Cuando el usuario gira el controlador giratorio en el sentido de las agujas del reloj un retén (clic), el VHAL debe usar la propiedad HW_ROTARY_INPUT con los siguientes int32Values ​​para enviar un evento a Android:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Un (1) retén.
  3. Visualización de objetivos.

La marca de tiempo del evento debe establecerse en el tiempo transcurrido en nanosegundos.

Una rotación de un (1) retén en sentido antihorario debería generar el mismo evento pero con -1 para el número de retenes.

Si se producen múltiples retenes de rotación en la misma dirección en rápida sucesión, el VHAL debe combinar los retenes en un solo evento para no sobrecargar el sistema con eventos. En este caso, la marca de tiempo del evento debe ser cuando ocurrió la primera parada de rotación. Los int32Values ​​deben incluir el número de nanosegundos entre retenes de rotación consecutivos.

Por ejemplo, la siguiente secuencia de rotaciones:

  • En el momento t0, el usuario giró un retén en sentido antihorario.
  • En el momento t0 + 5 ns, el usuario giró un retén en sentido antihorario.
  • En el momento t0 + 8 ns, el usuario giró un retén en sentido antihorario.

debería generar este evento:

  • Propiedad: HW_ROTARY_INPUT
  • Marca de tiempo: t0
  • int32Values :
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (tres retenes en sentido antihorario).
    3. Visualización de objetivos.
    4. 5 ns entre el primer y segundo retén.
    5. 3 ns entre el segundo y tercer retén.

Botón central

Cuando el usuario presiona el botón Central, el VHAL debe usar la propiedad HW_KEY_INPUT con los siguientes int32Values ​​para enviar un evento a Android:

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Visualización de objetivos.

Cuando el usuario suelta el controlador giratorio, el VHAL debe usar la misma propiedad y código clave con ACTION_UP .

No genere eventos repetidos cuando se mantenga presionado el botón central.

Botón de retroceso

Cuando el usuario presiona el botón Atrás, VHAL debe usar la propiedad HW_KEY_INPUT con los siguientes int32Values ​​para enviar un evento a Android:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Visualización de objetivos.

Cuando el usuario suelta el controlador giratorio, el VHAL debe usar la misma propiedad y código clave con ACTION_UP .

No se deben generar eventos repetidos mientras se mantiene presionado el botón Central.

Botón de inicio

Maneje el botón Inicio como lo haría con el botón Atrás pero con KEYCODE_HOME en lugar de KEYCODE_BACK .

Otros botones

Si el controlador giratorio incluye botones adicionales, VHAL puede manejarlos como quiera el OEM, ya que no se consideran parte del giratorio desde la perspectiva de Android. Por lo general, se manejan como los botones Atrás e Inicio, pero con códigos clave diferentes. Por ejemplo, KEYCODE_CALL o KEYCODE_MUSIC .

Configuración de compilación

La navegación giratoria es proporcionada por un servicio de accesibilidad llamado RotaryService . Para incluir este servicio en la imagen del sistema de su dispositivo, agregue la siguiente línea a su archivo MAKE:

PRODUCT_PACKAGES += CarRotaryController

Es posible que también desee incluir los siguientes paquetes en las compilaciones de depuración:

El servicio rotativo se habilita automáticamente cuando se inicia el dispositivo y cuando se produce un cambio de usuario. Esto garantiza que el usuario pueda utilizar el controlador giratorio durante la configuración.

Si usa la misma compilación para automóviles con y sin controlador giratorio, agregue CarRotaryController como se muestra arriba para que el código necesario se incluya en la compilación. Para evitar que el servicio rotativo se habilite en automóviles no rotativos, cree un RRO estático para superponer el recurso de cadena de rotaryService en packages/services/Car/service con una cadena vacía. Utilizará la misma compilación, pero tendrá configuraciones de producto independientes para dispositivos giratorios y no giratorios. Sólo este último incluye la superposición.

Personalización

Los OEM pueden personalizar la lógica de búsqueda de enfoque, el resaltado de enfoque y algunos elementos adicionales a través de superposiciones de recursos en las siguientes ubicaciones:

  • car-ui-library se encuentra en packages/apps/Car/libs/car-ui-lib
  • RotaryService se encuentra en packages/apps/Car/RotaryController
  • Core se encuentra en frameworks/base/core

Empujar la historia

El OEM puede configurar si cada uno de los dos tipos de historial de empuje está habilitado o no y, de ser así, el tamaño de la caché y la política de caducidad. Todo esto se hace anulando varios recursos de car-ui-library.

Caché del historial de enfoque

( Android 11 QPR3, Android 11 Coche, Android 12 )
Este caché por FocusArea almacena la vista enfocada más recientemente dentro del FocusArea para que pueda enfocarse al regresar al FocusArea . Este caché se puede configurar superponiendo los siguientes recursos car-ui-library:

  • car_ui_focus_history_cache_type :
    1. La caché está deshabilitada.
    2. La caché caducará después de un tiempo (ver más abajo).
    3. El caché nunca caducará.
  • car_ui_focus_history_expiration_period_ms : cuántos milisegundos antes de que caduque el caché si el tipo de caché se establece en dos (2) (ver arriba).

Caché del historial de FocusArea

( Android 11 QPR3, Android 11 Coche, Android 12 )
Este caché almacena un historial de empujones para que empujar en la dirección opuesta pueda devolver el foco a la misma FocusArea . Este caché se puede configurar superponiendo los siguientes recursos car-ui-library:

  • car_ui_focus_area_history_cache_type :
    1. La caché está deshabilitada.
    2. La caché caduca después de un tiempo (ver más abajo).
    3. El caché nunca caduca.
  • car_ui_focus_area_history_expiration_period_ms : cuántos milisegundos antes de que caduque el caché si el tipo de caché se establece en 2 (ver arriba).
  • car_ui_clear_focus_area_history_when_rotating : si se anula el caché cuando el usuario gira el controlador.

Rotación

( Android 11 QPR3, Android 11 Coche, Android 12 )
El OEM puede anular dos recursos enteros en RotaryService para especificar si hay aceleración, como la aceleración del mouse, para la rotación:

  • rotation_acceleration_3x_ms : Intervalo de tiempo (en milisegundos) utilizado para decidir si Google debe acelerar la rotación del controlador para detener la rotación. Si el intervalo entre este retén y el retén de rotación anterior es menor que este valor, se tratará como tres retenes de rotación. Configúrelo en 2147483647 para desactivar la aceleración 3×.
  • rotation_acceleration_2x_ms : similar a rotation_acceleration_3x_ms . Se utiliza para aceleración 2×. Configúrelo en 2147483647 para desactivar la aceleración 2×.

La aceleración funciona mejor cuando hay marcas de tiempo individuales para cada retén de rotación, como lo requiere VHAL. Si no están disponibles, el RotaryService asume que los retenes de rotación están espaciados 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),

Resaltado de enfoque

El OEM puede anular el resaltado de enfoque predeterminado en el marco de Android y varios recursos de resaltado de enfoque en car-ui-library.

Resaltado de enfoque predeterminado

El marco de Android proporciona un resaltado de enfoque predeterminado a través del atributo selectableItemBackground . En Theme.DeviceDefault , este atributo hace referencia a item_background.xml en Core . El OEM puede superponer item_background.xml para cambiar el elemento de diseño resaltado de enfoque predeterminado.

Este elemento de diseño normalmente debería ser StateListDrawable , que ajusta el fondo en función de diferentes combinaciones de estados, incluidos android:state_focused y android:state_pressed . Cuando el usuario usa el controlador giratorio para enfocar una vista, android:state_focused será true , pero android:state_pressed será false . Si luego el usuario presiona el botón central en el controlador giratorio, tanto android:state_focused como android:state_pressed serán true mientras el usuario mantenga presionado el botón. Cuando el usuario suelta el botón, solo android:state_focused permanecerá true .

car-ui-library utiliza un tema derivado de Theme.DeviceDefault . Como resultado, esta superposición afecta a las aplicaciones que usan esta biblioteca y a las aplicaciones que usan cualquier tema derivado de Theme.DeviceDefault . No afectará a las aplicaciones que usan un tema no relacionado, como Theme.Material .

Enfoque los recursos destacados en car-ui-library

El OEM puede anular varios recursos car-ui-library para controlar cómo se ve el resaltado de enfoque en vistas con un resaltado de enfoque no rectangular (como redondo o en forma de píldora) y en aplicaciones que usan un tema que no deriva de Theme.DeviceDefault . Estos recursos deben superponerse para que el resaltado de enfoque sea coherente con el elemento de resaltado de enfoque predeterminado .

( Android 11 QPR3, Android 11 Coche, Android 12 )
Los siguientes recursos se utilizan para indicar cuándo una vista está enfocada pero no presionada:

  • car_ui_rotary_focus_fill_color : Color de relleno.
  • car_ui_rotary_focus_stroke_color : color del contorno.
  • car_ui_rotary_focus_stroke_width : Grosor del contorno.

( Android 11 QPR3, Android 11 Coche, Android 12 )
Los siguientes recursos se utilizan para indicar cuándo una vista está enfocada y presionada:

  • car_ui_rotary_focus_pressed_fill_color : color de relleno.
  • car_ui_rotary_focus_pressed_stroke_color : color del contorno.
  • car_ui_rotary_focus_pressed_stroke_width : Grosor del contorno.

A veces, a un botón se le asigna un color de fondo sólido para llamar la atención del usuario, como en el ejemplo que se muestra. Esto puede hacer que el foco sea difícil de ver.

Botón con fondo sólido
Figura 2. Botón con fondo sólido

En esta situación, el desarrollador puede especificar un resaltado de enfoque personalizado utilizando colores secundarios :
  • ( Android 11 QPR3, Android 11 Coche, Android 12 )
    car_ui_rotary_focus_fill_secondary_color
    car_ui_rotary_focus_stroke_secondary_color
  • ( Androide 12 )
    car_ui_rotary_focus_pressed_fill_secondary_color
    car_ui_rotary_focus_pressed_stroke_secondary_color

Cualquiera de los colores puede ser transparente y cualquiera de las dimensiones puede ser cero si, por ejemplo, desea sólo un relleno o sólo un contorno.

Resaltado del área de enfoque

( Android 11 QPR3, Android 11 Coche, Android 12 )
FocusArea puede dibujar dos tipos de resaltado cuando uno de sus descendientes está enfocado. Ambos se pueden utilizar en conjunto, si se desea. Esta característica está deshabilitada de forma predeterminada en AOSP, pero se puede habilitar anulando los recursos de car-ui-library:

  • car_ui_enable_focus_area_foreground_highlight : dibuja un resaltado encima del FocusArea y sus descendientes. En AOSP, este elemento de diseño es un contorno alrededor del FocusArea . Los OEM pueden anular el elemento de diseño car_ui_focus_area_foreground_highlight .
  • car_ui_enable_focus_area_background_highlight : dibuja un resaltado encima del FocusArea pero detrás de sus descendientes. En AOSP, este dibujable es un relleno sólido. Los OEM pueden anular el elemento de diseño car_ui_focus_area_background_highlight .

Editores de métodos de entrada

Los editores de métodos de entrada (IME) son métodos de entrada. Por ejemplo, un teclado en pantalla.

( Android 11 QPR3, Android 11 Coche, Android 12 )
El OEM debe superponer el recurso de cadena default_touch_input_method en RotaryService para especificar el ComponentName del componente del IME táctil. Por ejemplo, si el OEM utiliza el IME proporcionado con Android Automotive, debe especificar com.google.android.apps.automotive.inputmethod/.InputMethodService .

( Android 11 QPR3, Android 11 Coche, Android 12 )
Si el OEM ha creado un IME específicamente para Rotary, debe especificar su ComponentName en el recurso rotary_input_method . Si este recurso está superpuesto, el IME especificado se utiliza cada vez que el usuario interactúa con la unidad principal mediante el desplazamiento, la rotación y el botón central del controlador giratorio. Cuando el usuario toque la pantalla, se utilizará el IME anterior. El botón Atrás (y otros botones del controlador giratorio) no tienen ningún efecto en la selección de IME. Si este recurso no está superpuesto, no se produce ningún cambio de IME. Carboard no admite rotativo, por lo que el usuario no puede ingresar texto a través del controlador rotativo si el OEM no ha proporcionado un IME rotativo.

RotaryIME es un IME rotativo de demostración. Si bien es básico, es suficiente probar el cambio automático de IME descrito anteriormente. El código fuente de RotaryIME se puede encontrar en packages/apps/Car/tests/RotaryIME/ .

Empujes fuera de pantalla

De forma predeterminada, cuando el usuario intenta salir del borde de la pantalla, no sucede nada. El OEM puede configurar lo que debe ocurrir en cada una de las cuatro direcciones especificando cualquier combinación de:

  1. Una acción global definida por AccessibilityService . Por ejemplo, GLOBAL_ACTION_BACK .
  2. Un código clave, como KEYCODE_BACK .
  3. Intento de iniciar una actividad representada como una URL.

( Android 11 QPR3, Android 11 Coche, Android 12 )
Estos se especifican superponiendo los siguientes recursos de matriz en RotaryService :

  • off_screen_nudge_global_actions : conjunto de acciones globales que se realizarán cuando el usuario se mueva hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha fuera del borde de la pantalla. No se realiza ninguna acción global si el elemento relevante de esta matriz es -1.
  • off_screen_nudge_key_codes : conjunto de códigos clave de eventos de clic que se inyectan cuando el usuario se mueve hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha fuera del borde de la pantalla. No se inyectan eventos si el elemento relevante de esta matriz es 0 ( KEYCODE_UNKNOWN ).
  • off_screen_nudge_intents : conjunto de intentos para iniciar una actividad cuando el usuario se mueve hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha fuera del borde de la pantalla. No se inicia ninguna actividad si el elemento relevante de esta matriz está vacío.

Otras configuraciones

Debe superponer los siguientes recursos RotaryService :

  • ( Android 11 QPR3, Android 11 Coche, Android 12 )
    config_showHeadsUpNotificationOnBottom : valor booleano para representar si las notificaciones emergentes deben mostrarse en la parte inferior en lugar de en la parte superior. Debe tener el mismo valor que el recurso booleano config_showHeadsUpNotificationOnBottom en frameworks/base/packages/CarSystemUI/res/values/config.xml
  • ( Android 11 QPR3, Android 11 Coche, Android 12 )
    notification_headsup_card_margin_horizontal : margen izquierdo y derecho para la ventana de notificación directa. Debe tener el mismo valor que el recurso de dimensión notification_headsup_card_margin_horizontal en packages/apps/Car/Notification/res/values/dimens.xml
  • ( Androide 12 )
    excluded_application_overlay_window_titles : una matriz de títulos de ventanas que no deben considerarse ventanas superpuestas. Esto debe incluir títulos de ventanas de aplicaciones que representen TaskViews o TaskDisplayAreas . De forma predeterminada, esta lista contiene sólo "Mapas".

Puede superponer el siguiente recurso RotaryService :

  • ( Android 11 QPR3, Android 11 Coche, Android 12 )
    long_press_ms : valor entero para representar cuántos milisegundos se debe mantener presionado el botón central para activar una pulsación larga. Cero indica que se debe utilizar el tiempo de espera de pulsación larga predeterminado del sistema. Este es el valor predeterminado.