En esta página, se describe cómo procesar entradas rotativas en el VHAL, configurar tu compilación para incluir el servicio rotativo y personalizar la experiencia rotativa en todas las apps. Para las apps de OEM preinstaladas, como un selector proporcionado por el OEM, consulta Car UI Library (car-ui-library).
VHAL
Un controlador rotatorio admite las siguientes acciones:
- Desplazar hacia arriba, abajo, izquierda y derecha
- Rotar en sentido horario y antihorario
- Presiona el botón central.
- Presiona el botón Atrás.
- Presiona el botón de inicio.
- Presiona otros botones, como Teléfono y Multimedia.
Consulta hardware/interfaces/automotive/vehicle/2.0/types.hal para obtener documentación sobre las propiedades del sistema y el int32Values correspondiente.
El VHAL debe controlar estas acciones:
Aviso
Cuando el usuario presiona el controlador rotatorio hacia la derecha, el VHAL debe usar la propiedad HW_KEY_INPUT con el siguiente int32Values para enviar un evento a Android:
ACTION_DOWNKEYCODE_SYSTEM_NAVIGATION_RIGHT- Es la pantalla de destino.
Cuando el usuario suelta el controlador rotatorio, el VHAL debe usar la misma propiedad y el mismo código de tecla con ACTION_UP. Los avisos en otras direcciones deben usar los códigos de teclas correspondientes.
No hay códigos de teclas para las diagonales, pero el VHAL puede combinar un evento horizontal y uno vertical para producir una diagonal si el hardware admite diagonales. Por ejemplo, si se desplaza hacia arriba y hacia la izquierda, debería producirse lo siguiente:
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWNHW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
Si sueltas el controlador giratorio en cualquier orden (y, luego, de forma sucesiva), se debería producir lo siguiente:
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UPHW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP
El usuario puede presionar el controlador giratorio en dirección perpendicular antes de soltarlo. Por ejemplo, en la siguiente situación:
Esto debería generar la siguiente secuencia de eventos:
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWNHW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWNHW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UPHW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP
No se deben generar eventos de repetición mientras se mantiene el controlador rotatorio en una dirección.
Rotar
Cuando el usuario gira el control rotatorio en el sentido de las agujas del reloj un tope (clic), el VHAL debe usar la propiedad HW_ROTARY_INPUT con el siguiente int32Values para enviar un evento a Android:
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION- Un (1) tope
- Es la pantalla de destino.
La marca de tiempo del evento debe establecerse en el tiempo transcurrido en nanosegundos.
Un (1) tope de rotación en sentido contrario a las agujas del reloj debe generar el mismo evento, pero con -1 para la cantidad de topes.
Si se producen varios topes de rotación en la misma dirección de forma rápida y sucesiva, el VHAL debe combinar los topes en un solo evento para no sobrecargar el sistema con eventos.
En este caso, la marca de tiempo del evento debe ser el momento en que se produjo el primer tope de rotación.
El int32Values debe incluir la cantidad de nanosegundos entre los topes consecutivos de rotación.
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 contrario a las agujas del reloj.
- En el tiempo t0 + 8 ns, el usuario giró un tope en sentido contrario a las agujas del reloj.
debería generar este evento:
- Propiedad:
HW_ROTARY_INPUT - Marca de tiempo:
t0 int32Values:ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION- -3 (tres topes en sentido contrario a las manecillas del reloj).
- Es la pantalla de destino.
- 5 ns entre el primer y el segundo tope
- 3 ns entre el segundo y el tercer tope.
Centrar botón
Cuando el usuario presiona el botón Center, el VHAL debe usar la propiedad HW_KEY_INPUT con el siguiente int32Values para enviar un evento a Android:
ACTION_DOWNKEYCODE_DPAD_CENTER- Es la pantalla de destino.
Cuando el usuario suelta el controlador rotatorio, el VHAL debe usar la misma propiedad y el mismo código de tecla con ACTION_UP.
No se generan eventos de repetición cuando se mantiene presionado el botón Centrar.
Botón Atrás
Cuando el usuario presiona el botón Atrás, el VHAL debe usar la propiedad HW_KEY_INPUT con el siguiente int32Values para enviar un evento a Android:
ACTION_DOWNKEYCODE_BACK- Es la pantalla de destino.
Cuando el usuario suelta el controlador rotatorio, el VHAL debe usar la misma propiedad y el mismo código de tecla con ACTION_UP.
No se deben generar eventos de repetición mientras se mantiene presionado el botón central.
Botón Home
Controla el botón de inicio como lo harías 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 controlarlos como lo desee el OEM, ya que no se consideran parte del rotatorio desde la perspectiva de Android.
Por lo general, se controlan como los botones Atrás y Principal, pero con diferentes códigos de teclas.
Por ejemplo, KEYCODE_CALL o KEYCODE_MUSIC.
Configuración de compilación
La navegación rotatoria se proporciona a través de un servicio de accesibilidad llamado RotaryService.
Para incluir este servicio en la imagen del sistema de tu dispositivo, agrega la siguiente línea a tu archivo makefile:
PRODUCT_PACKAGES += CarRotaryController
También puedes incluir los siguientes paquetes en las compilaciones de depuración:
RotaryPlaygroundUna app de referencia para la entrada rotativa (consulta RotaryPlayground).RotaryIMEUn IME rotatorio de demostración (consulta Editores de métodos de entrada).CarRotaryImeRROLa superposición paraRotaryIME.
El servicio rotatorio se habilita automáticamente cuando se inicia el dispositivo y cuando se produce un cambio de usuario. Esto garantiza que el usuario pueda usar el controlador giratorio durante la configuración.
Si usas la misma compilación para automóviles con y sin control rotatorio, agrega CarRotaryController como se mostró anteriormente para que se incluya el código necesario en la compilación. Para evitar que se habilite el servicio de rotary en automóviles que no son de rotary, crea un RRO estático para superponer el recurso de cadena rotaryService en packages/services/Car/service con una cadena vacía. Usarás la misma compilación, pero tendrás 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 elemento destacado 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 RotaryServicese encuentra enpackages/apps/Car/RotaryController.Corese encuentra enframeworks/base/core.
Historial de avisos
El OEM puede configurar si se habilita o no cada uno de los dos tipos de historial de sugerencias y, si es así, el tamaño de la caché y la política de vencimiento. Todo esto se hace anulando varios recursos de car-ui-library.
Caché del historial de enfoque
(Android 11 QPR3, Android 11 Car, Android 12)
Esta caché por FocusArea almacena la vista enfocada más recientemente dentro del FocusArea para que se pueda enfocar cuando se vuelva a desplazar al FocusArea.
Esta caché se puede configurar superponiendo los siguientes recursos de car-ui-library:
-
car_ui_focus_history_cache_type:- La caché está inhabilitada.
- La caché vencerá después de un tiempo (consulta a continuación).
- La caché nunca vencerá.
car_ui_focus_history_expiration_period_ms: Cantidad de milisegundos antes de que venza la caché si el tipo de caché se establece en dos (2) (consulta más arriba).
Caché del historial de FocusArea
(Android 11 QPR3, Android 11 Car, Android 12)
Esta caché almacena un historial de sugerencias para que las sugerencias en la dirección opuesta puedan devolver el enfoque al mismo FocusArea. Esta caché se puede configurar superponiendo los siguientes recursos de car-ui-library:
-
car_ui_focus_area_history_cache_type:- La caché está inhabilitada.
- La caché vence después de un tiempo (consulta a continuación).
- La caché nunca vence.
car_ui_focus_area_history_expiration_period_ms: Cantidad de milisegundos antes de que venza la caché si el tipo de caché se establece en 2 (consulta más arriba).car_ui_clear_focus_area_history_when_rotating: Indica si se debe anular la caché cuando el usuario rota el controlador.
Rotación
(Android 11 QPR3, Android 11 Car, Android 12)
El OEM puede anular dos recursos de números 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) que se usa para decidir si Google debe acelerar la rotación del controlador para un tope de rotación. Si el intervalo entre este tope y el tope anterior de rotación es menor que este valor, se tratará como tres topes de rotación. Establece este valor en 2147483647 para inhabilitar la aceleración de 3×.rotation_acceleration_2x_ms: Similar arotation_acceleration_3x_ms. Se usa para la aceleración de 2×. Configúralo como2147483647para inhabilitar la aceleración 2×.
La aceleración funciona mejor cuando hay marcas de tiempo individuales para cada tope de rotación, como lo requiere la VHAL. Si no están disponibles, RotaryService supone que los topes de rotación están espaciados de manera uniforme.
/** * 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),
Destacado de enfoque
El OEM puede anular el elemento destacado de enfoque predeterminado en el framework de Android y varios recursos de elementos destacados de enfoque en car-ui-library.
Destacado de enfoque predeterminado
El framework 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 drawable destacado de enfoque predeterminado.
Por lo general, este elemento de diseño debe ser un StateListDrawable, que ajusta el fondo según diferentes combinaciones de estados, incluidos android:state_focused y android:state_pressed. Cuando el usuario usa el controlador rotatorio para enfocar una vista, android:state_focused será true, pero android:state_pressed será false. Si el usuario presiona el botón central del control rotatorio, tanto android:state_focused como android:state_pressed serán true mientras el usuario mantenga presionado el botón.
Cuando el usuario suelte el botón, solo permanecerá android:state_focusedtrue.
car-ui-library usa un tema derivado de Theme.DeviceDefault. Como resultado, esta superposición afecta a las apps que usan esta biblioteca y a las apps que usan cualquier tema derivado de Theme.DeviceDefault. No afectará a las apps que usen un tema no relacionado, como Theme.Material.
Recursos de enfoque destacados en car-ui-library
El OEM puede anular varios recursos de car-ui-library para controlar el aspecto del resaltado de enfoque en vistas con un resaltado de enfoque no rectangular (como redondo o en forma de píldora) y en apps que usan un tema que no deriva de Theme.DeviceDefault. Estos recursos deben superponerse para que el resaltado del enfoque sea coherente con el elemento de diseño resaltado del enfoque predeterminado.
(Android 11 QPR3, Android 11 Car, Android 12)
Los siguientes recursos se usan para indicar cuándo se enfoca una vista, pero no se presiona:
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 Car, Android 12)
Los siguientes recursos se usan para indicar cuándo se enfoca y presiona una vista:
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, se le asigna un color de fondo sólido a un botón para llamar la atención del usuario, como en el ejemplo que se muestra. Esto puede dificultar la visualización del enfoque destacado.
En esta situación, el desarrollador puede especificar un enfoque destacado personalizado con colores secundarios:
- (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
Cualquiera de los colores puede ser transparente y cualquiera de las dimensiones puede ser cero si, por ejemplo, solo quieres un relleno o solo un contorno.
Destacado de FocusArea
(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea puede dibujar dos tipos de resaltado cuando uno de sus elementos secundarios tiene el enfoque. Ambos pueden usarse en conjunto, si lo deseas. Esta función está inhabilitada 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 elemento destacado sobre elFocusAreay sus elementos secundarios. En el AOSP, este elemento de diseño es un contorno alrededor deFocusArea. Los OEM pueden anular el elementocar_ui_focus_area_foreground_highlightdibujable.car_ui_enable_focus_area_background_highlight: Dibuja un resaltado sobre el elementoFocusArea, pero detrás de sus elementos secundarios. En el AOSP, este elemento de diseño es un relleno sólido. Los OEM pueden anular el elementocar_ui_focus_area_background_highlightdibujable.
Editores de método 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 Car, Android 12)
El OEM debe superponer el recurso de cadena default_touch_input_method en RotaryService para especificar el ComponentName del IME basado en el tacto. Por ejemplo, si el OEM usa el IME proporcionado con Android Automotive, debe especificar com.google.android.apps.automotive.inputmethod/.InputMethodService.
(Android 11 QPR3, Android 11 Car, Android 12)
Si el OEM creó un IME específicamente para el control rotatorio, debe especificar su ComponentName en el recurso rotary_input_method. Si este recurso se superpone, se usa el IME especificado cada vez que el usuario interactúa con la unidad principal a través de los botones de desplazamiento, rotación y centrado del controlador rotativo. Cuando el usuario toque la pantalla, se usará el IME anterior. El botón Atrás (y otros botones del control rotatorio) no tienen efecto en la selección del IME. Si este recurso no se superpone, no se produce ningún cambio de IME. Cardboard no admite la entrada rotativa, por lo que el usuario no puede ingresar texto a través del controlador rotativo si el OEM no proporcionó un IME rotativo.
RotaryIME es un IME rotatorio de demostración. Si bien es básico, es suficiente para probar el cambio automático de IME que se describió anteriormente. El código fuente de RotaryIME se encuentra en packages/apps/Car/tests/RotaryIME/.
Sugerencias fuera de la pantalla
De forma predeterminada, cuando el usuario intenta deslizar el dedo fuera del 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 lo siguiente:
- Es una acción global definida por
AccessibilityService. Por ejemplo,GLOBAL_ACTION_BACK. - Un código de clave, como
KEYCODE_BACK - Es un intent para iniciar una actividad representada como una URL.
(Android 11 QPR3, Android 11 Car, Android 12)
Estos se especifican superponiendo los siguientes recursos de matriz en RotaryService:
off_screen_nudge_global_actions: Es un array de acciones globales que se realizan cuando el usuario desliza el dedo hacia arriba, abajo, la izquierda o la derecha desde el borde de la pantalla. No se realiza ninguna acción global si el elemento correspondiente de este array es -1.off_screen_nudge_key_codes: Es un array de códigos de teclas de eventos de clic que se insertarán cuando el usuario se desplace hacia arriba, abajo, la izquierda o la derecha desde el borde de la pantalla. No se insertan eventos si el elemento pertinente de este array es 0 (KEYCODE_UNKNOWN).off_screen_nudge_intents: Es un array de intents para iniciar una actividad cuando el usuario se desplaza hacia arriba, abajo, izquierda o derecha desde el borde de la pantalla. No se inicia ninguna actividad si el elemento pertinente de este array está vacío.
Otros parámetros de configuración
Debes superponer los siguientes recursos de RotaryService:
- (Android 11 QPR3, Android 11 Car, Android 12)
config_showHeadsUpNotificationOnBottom: Es un valor booleano que representa 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_showHeadsUpNotificationOnBottomenframeworks/base/packages/CarSystemUI/res/values/config.xml. - (Android 11 QPR3, Android 11 Car, Android 12)
notification_headsup_card_margin_horizontal: Margen izquierdo y derecho de la ventana de notificación emergente. Debe tener el mismo valor que el recurso de dimensiónnotification_headsup_card_margin_horizontalenpackages/apps/Car/Notification/res/values/dimens.xml. - (Android 12)
excluded_application_overlay_window_titles: Es un array de títulos de ventanas que no se deben considerar ventanas de superposición. Esto debe incluir los títulos de las ventanas de la app que representanTaskViewsoTaskDisplayAreas. De forma predeterminada, esta lista solo contiene "Maps".
Puedes superponer el siguiente recurso RotaryService:
- (Android 11 QPR3, Android 11 Car, Android 12)
long_press_ms: Valor entero que representa la cantidad de milisegundos que se debe mantener presionado el botón central para activar una presión prolongada. El valor cero indica que se debe usar el tiempo de espera predeterminado del sistema para la presión prolongada. Este es el valor predeterminado.