Este artículo describe cómo procesar entradas rotativas en VHAL, configurar su compilación para incluir el servicio rotativo y cómo personalizar la experiencia rotatoria en todas las aplicaciones. Para aplicaciones OEM preinstaladas, como un iniciador proporcionado por OEM, consulte Biblioteca de interfaz de usuario de automóvil (car-ui-library) .
VHAL
Un controlador giratorio admite las siguientes acciones:
- Empuje hacia arriba, abajo, izquierda y derecha.
- Girar en sentido horario y antihorario.
- Presiona el botón central.
- Presiona el botón de atrás.
- Presiona 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 los int32Values
correspondientes.
El VHAL debe manejar estas acciones:
Empujar
Cuando el usuario empuja el control giratorio hacia la derecha, el VHAL debe usar la propiedad HW_KEY_INPUT
con los siguientes int32Values
para enviar un evento a Android:
-
ACTION_DOWN
-
KEYCODE_SYSTEM_NAVIGATION_RIGHT
- Visualización de objetivos.
Cuando el usuario suelta el control giratorio, el VHAL debe usar la misma propiedad y código clave con ACTION_UP
. Los empujones en otras direcciones deben usar los códigos clave correspondientes.
No hay códigos clave para las 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), la liberación del controlador giratorio 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 una dirección perpendicular antes de soltarlo. Por ejemplo, el siguiente escenario:
Esto debería generar la siguiente secuencia 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
No se deben generar eventos repetidos mientras el control giratorio se mantiene en una dirección.
Girar
Cuando el usuario gira el controlador giratorio en el sentido de las agujas del reloj un tope (clic), el VHAL debe usar la propiedad HW_ROTARY_INPUT
con los siguientes int32Values
para enviar un evento a Android:
-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- Un (1) retén.
- 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 ocurren 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ó el primer tope de rotación. Los int32Values
deben incluir el número de nanosegundos entre detenciones de rotación consecutivas.
Por ejemplo, la siguiente secuencia de rotaciones:
- En el momento t0, el usuario giró un tope en sentido contrario a las agujas del reloj.
- En el momento t0 + 5 ns, el usuario giró un tope en sentido antihorario.
- En el momento t0 + 8 ns, el usuario giró un tope en sentido antihorario.
debe generar este evento:
- Propiedad:
HW_ROTARY_INPUT
- Marca de tiempo:
t0
-
int32Values
:-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- -3 (tres retenes en sentido contrario a las agujas del reloj).
- Visualización de objetivos.
- 5 ns entre el primer y el segundo retén.
- 3 ns entre el segundo y el tercer retén.
-
Botón central
Cuando el usuario presiona el botón Centro, VHAL debe usar la propiedad HW_KEY_INPUT
con los siguientes int32Values
para enviar un evento a Android:
-
ACTION_DOWN
-
KEYCODE_DPAD_CENTER
- Visualización de objetivos.
Cuando el usuario suelta el control giratorio, el VHAL debe usar la misma propiedad y código clave con ACTION_UP
.
No genere eventos repetidos cuando se mantiene 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:
-
ACTION_DOWN
-
KEYCODE_BACK
- Visualización de objetivos.
Cuando el usuario suelta el control 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 rotatorio incluye botones adicionales, el VHAL puede manejarlos como le guste al OEM, ya que no se consideran parte del rotativo desde la perspectiva de Android. Por lo general, se manejan como los botones Atrás e Inicio, pero con diferentes códigos clave. Por ejemplo, KEYCODE_CALL
o KEYCODE_MUSIC
.
Configuración de compilación
La navegación rotatoria 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
También es posible que desee incluir los siguientes paquetes en las compilaciones de depuración:
-
RotaryPlayground
Una aplicación de referencia para rotativo (ver RotaryPlayground ). -
RotaryIME
Un IME rotativo de demostración (consulte Editores de métodos de entrada ). -
CarRotaryImeRRO
La superposición paraRotaryIME
.
El servicio rotativo se activa 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 que no sean rotativos, cree un RRO estático para superponer el rotaryService
de cadena de servicio rotativo en packages/services/Car/service
con una cadena vacía. Usará la misma compilación, pero tendrá configuraciones de productos separadas, para dispositivos rotativos y no rotativos. Solo 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 enpackages/apps/Car/RotaryController
-
Core
se encuentra enframeworks/base/core
Historial de empujones
El OEM puede configurar si cada uno de los dos tipos de historial de nudge está habilitado o no y, de ser así, el tamaño de caché y la política de caducidad. Todo esto se hace anulando varios recursos car-ui-library.
Caché de historial de enfoque
( Android 11 QPR3, Android 11 Coche, Android 12 )
Esta FocusArea
caché por área de enfoque almacena la vista enfocada más recientemente dentro del área de FocusArea
para que se pueda enfocar al regresar al área de FocusArea
. Este caché se puede configurar superponiendo los siguientes recursos car-ui-library:
-
car_ui_focus_history_cache_type
:- El caché está deshabilitado.
- El caché caducará después de un tiempo (ver más abajo).
- El caché nunca caducará.
-
car_ui_focus_history_expiration_period_ms
: cuántos milisegundos antes de que caduque la caché si el tipo de caché se establece en dos (2) (ver arriba).
Caché de historial de FocusArea
( Android 11 QPR3, Android 11 Coche, Android 12 )
Este caché almacena un historial de toques 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
:- El caché está deshabilitado.
- El caché caduca después de un tiempo (ver más abajo).
- El caché nunca caduca.
-
car_ui_focus_area_history_expiration_period_ms
: cuántos milisegundos antes de que caduque la caché si el tipo de caché se establece en 2 (ver arriba). -
car_ui_clear_focus_area_history_when_rotating
: si se anula la memoria 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 un tope de 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. Establézcalo en 2147483647 para deshabilitar la aceleración 3×. -
rotation_acceleration_2x_ms
: similar arotation_acceleration_3x_ms
. Se utiliza para una aceleración de 2×. Establézcalo en2147483647
para deshabilitar la aceleración 2×.
La aceleración funciona mejor cuando hay marcas de tiempo individuales para cada tope de rotación, según lo requiera el VHAL. Si no están disponibles, RotaryService
asume que los topes 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),
Foco resaltado
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.
Destacado de enfoque predeterminado
El marco de trabajo 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 resaltado de enfoque predeterminado dibujable.
Este elemento de diseño normalmente debe ser un 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 control giratorio para enfocar una vista, android:state_focused
será true
, pero android:state_pressed
será false
. Si el usuario luego presiona el botón central en el control giratorio, tanto android:state_focused
como android:state_pressed
serán true
mientras el usuario mantiene presionado el botón. Cuando el usuario suelta el botón, solo android:state_focused
seguirá siendo true
.
car-ui-library usa un tema derivado de Theme.DeviceDefault
. Como resultado, esta superposición afecta a las aplicaciones que usan esta biblioteca y las aplicaciones que usan cualquier tema derivado de Theme.DeviceDefault
. No afectará a las aplicaciones que usan un tema no relacionado, como Theme.Material
.
Enfocar recursos destacados en car-ui-library
El OEM puede anular varios recursos de la biblioteca de interfaz de usuario del automóvil para controlar cómo se ve el resaltado de enfoque en las 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 se deriva de Theme.DeviceDefault
. Estos recursos deben superponerse para que el resaltado de enfoque sea coherente con el elemento de diseño 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 da 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 punto culminante del enfoque sea difícil de ver.
En esta situación, el desarrollador puede especificar un resaltado de enfoque personalizado usando colores secundarios :- ( Android 11 QPR3, Android 11 Coche, 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
Cualquiera de los colores puede ser transparente y cualquiera de las dimensiones puede ser cero si, por ejemplo, desea solo un relleno o solo un contorno.
Área de enfoque destacada
( 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 usar en conjunto, si se desea. Esta función 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
: Dibuje un resaltado en la parte superior deFocusArea
y sus descendientes. En AOSP, este dibujable es un contorno alrededor delFocusArea
. Los OEM pueden anular el elemento decar_ui_focus_area_foreground_highlight
. -
car_ui_enable_focus_area_background_highlight
: Dibuje un resaltado en la parte superior delFocusArea
pero detrás de sus descendientes. En AOSP, este dibujable es un relleno sólido. Los OEM pueden anular el elemento decar_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 el RotaryService
para especificar el ComponentName
del IME táctil. Por ejemplo, si el OEM usa el IME provisto 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 rotativo, debe especificar su ComponentName
en el recurso rotary_input_method
. Si este recurso está superpuesto, el IME especificado se usa cada vez que el usuario interactúa con la unidad principal a través del botón de empuje, rotación y centro del control giratorio. Cuando el usuario toca la pantalla, se utilizará el IME anterior. El botón Atrás (y otros botones del control giratorio) no tienen 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 rotatorio si el OEM no ha proporcionado un IME rotatorio.
RotaryIME
es un IME rotativo de demostración. Si bien es básico, basta con probar el cambio automático de IME descrito anteriormente. El código fuente de RotaryIME
se puede encontrar en packages/apps/Car/tests/RotaryIME/
.
Empujones fuera de pantalla
De forma predeterminada, cuando el usuario intenta empujar el borde de la pantalla, no sucede nada. El OEM puede configurar lo que debe ocurrir para cada una de las cuatro direcciones especificando cualquier combinación de:
- Una acción global definida por
AccessibilityService
. Por ejemplo,GLOBAL_ACTION_BACK
. - Un código clave, como
KEYCODE_BACK
. - Una intención de lanzar 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
: Matriz de acciones globales para realizar cuando el usuario empuja hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha desde el 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
: Matriz de códigos clave de eventos de clic para inyectar cuando el usuario empuja hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha desde el borde de la pantalla. No se inyectan eventos si el elemento relevante de esta matriz es 0 (KEYCODE_UNKNOWN
). -
off_screen_nudge_intents
: matriz de intentos para iniciar una actividad cuando el usuario empuja hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha desde el 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 booleanoconfig_showHeadsUpNotificationOnBottom
enframeworks/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 emergente. Debe tener el mismo valor que el recurso denotification_headsup_card_margin_horizontal
enpackages/apps/Car/Notification/res/values/dimens.xml
- ( Android 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 representenTaskViews
oTaskDisplayAreas
. De forma predeterminada, esta lista contiene solo "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 prolongada. Cero indica que se debe usar el tiempo de espera de pulsación prolongada predeterminado del sistema. Este es el valor predeterminado.