Guide d'intégration pour les OEM

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Cet article décrit comment traiter les entrées rotatives dans le VHAL, configurer votre build pour inclure le service rotatif et comment personnaliser l'expérience rotative dans toutes les applications. Pour les applications OEM préinstallées, telles qu'un lanceur fourni par l'OEM, consultez Car UI Library (car-ui-library) .

VHAL

Un contrôleur rotatif prend en charge les actions suivantes :

  • Poussez vers le haut, le bas, la gauche et la droite.
  • Tourner dans le sens des aiguilles d'une montre et dans le sens inverse des aiguilles d'une montre.
  • Appuyez sur le bouton central.
  • Appuyez sur le bouton précédent.
  • Appuyez sur le bouton Accueil.
  • Appuyez sur d'autres boutons, tels que Téléphone et Médias.

Voir hardware/interfaces/automotive/vehicle/2.0/types.hal pour la documentation sur les propriétés système et les int32Values ​​correspondantes.

Le VHAL doit gérer ces actions :

Coup de coude

Lorsque l'utilisateur pousse le contrôleur rotatif vers la droite, le VHAL doit utiliser la propriété HW_KEY_INPUT avec les int32Values ​​suivantes pour envoyer un événement à Android :

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Affichage cible.

Lorsque l'utilisateur relâche le contrôleur rotatif, le VHAL doit utiliser la même propriété et le même code clé avec ACTION_UP . Les coups de pouce dans d'autres directions doivent utiliser les codes correspondants.

Il n'y a pas de codes clés pour les diagonales mais le VHAL peut combiner un événement horizontal et vertical pour produire une diagonale si le matériel prend en charge les diagonales. Par exemple, pousser vers le haut et vers la gauche devrait produire :

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN

Dans l'un ou l'autre ordre (et par la suite), le relâchement du contrôleur rotatif devrait produire :

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

L'utilisateur peut pousser le bouton rotatif dans une direction perpendiculaire avant de le relâcher. Par exemple, le scénario suivant :

Sens perpendiculaire
Figure 1. Direction perpendiculaire

Cela devrait générer la séquence d'événements suivante :

  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

Aucun événement de répétition ne doit être généré lorsque le contrôleur rotatif est maintenu dans une direction.

Tourner

Lorsque l'utilisateur tourne le contrôleur rotatif dans le sens des aiguilles d'une montre d'un cran (clic), le VHAL doit utiliser la propriété HW_ROTARY_INPUT avec les int32Values ​​suivantes pour envoyer un événement à Android :

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Une (1) détente.
  3. Affichage cible.

L'horodatage de l'événement doit être défini sur le temps écoulé en nanosecondes.

Une rotation d'un (1) cran dans le sens antihoraire devrait générer le même événement mais avec -1 pour le nombre de crans.

Si plusieurs crans de rotation dans le même sens se succèdent rapidement, le VHAL doit combiner les crans en un seul événement afin de ne pas surcharger le système avec des événements. Dans ce cas, l'horodatage de l'événement doit correspondre au moment où le premier cran de rotation s'est produit. Les int32Values ​​doivent inclure le nombre de nanosecondes entre les crans de rotation consécutifs.

Par exemple, la séquence de rotations suivante :

  • Au temps t0, l'utilisateur a tourné un cran dans le sens inverse des aiguilles d'une montre.
  • Au temps t0 + 5 ns, l'utilisateur a tourné un cran dans le sens inverse des aiguilles d'une montre.
  • Au temps t0 + 8 ns, l'utilisateur a tourné un cran dans le sens inverse des aiguilles d'une montre.

devrait générer cet événement :

  • Propriété : HW_ROTARY_INPUT
  • Horodatage : t0
  • int32Values :
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (trois crans dans le sens antihoraire).
    3. Affichage cible.
    4. 5 ns entre le premier et le second cran.
    5. 3 ns entre le deuxième et le troisième cran.

Bouton central

Lorsque l'utilisateur appuie sur le bouton central, le VHAL doit utiliser la propriété HW_KEY_INPUT avec les int32Values ​​suivantes pour envoyer un événement à Android :

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Affichage cible.

Lorsque l'utilisateur relâche le contrôleur rotatif, le VHAL doit utiliser la même propriété et le même code clé avec ACTION_UP .

Ne génère pas d'événements répétés lorsque le bouton central est maintenu enfoncé.

Bouton Retour

Lorsque l'utilisateur appuie sur le bouton Précédent, le VHAL doit utiliser la propriété HW_KEY_INPUT avec les int32Values ​​suivantes pour envoyer un événement à Android :

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Affichage cible.

Lorsque l'utilisateur relâche le contrôleur rotatif, le VHAL doit utiliser la même propriété et le même code clé avec ACTION_UP .

Aucun événement de répétition ne doit être généré lorsque le bouton central est maintenu enfoncé.

Bouton d'accueil

Manipulez le bouton Home comme vous le feriez avec le bouton Back mais avec KEYCODE_HOME au lieu de KEYCODE_BACK .

Autres boutons

Si le contrôleur rotatif comprend des boutons supplémentaires, le VHAL peut les gérer comme l'OEM le souhaite car ils ne sont pas considérés comme faisant partie du rotatif du point de vue d'Android. Ceux-ci sont généralement gérés comme les boutons Retour et Accueil mais avec des codes clés différents. Par exemple, KEYCODE_CALL ou KEYCODE_MUSIC .

Construire la configuration

La navigation Rotary est fournie par un service d'accessibilité appelé RotaryService . Pour inclure ce service dans l'image système de votre appareil, ajoutez la ligne suivante à votre makefile :

PRODUCT_PACKAGES += CarRotaryController

Vous pouvez également inclure les packages suivants dans les versions de débogage :

Le service rotatif est activé automatiquement au démarrage de l'appareil et lorsqu'un changement d'utilisateur se produit. Cela garantit que l'utilisateur peut utiliser le contrôleur rotatif pendant la configuration.

Si vous utilisez la même version pour les voitures avec et sans contrôleur rotatif, ajoutez CarRotaryController comme indiqué ci-dessus afin que le code nécessaire soit inclus dans la version. Pour empêcher l'activation du service rotatif sur les voitures non rotatives, créez un RRO statique pour superposer la ressource de chaîne rotaryService dans packages/services/Car/service avec une chaîne vide. Vous utiliserez la même version, mais avec des configurations de produit distinctes, pour les appareils rotatifs et non rotatifs. Seul ce dernier inclut la superposition.

Personnalisation

Les OEM peuvent personnaliser la logique de recherche de focus, la mise en surbrillance du focus et certains éléments supplémentaires via des superpositions de ressources aux emplacements suivants :

  • car-ui-library se trouve dans packages/apps/Car/libs/car-ui-lib
  • RotaryService se trouve dans packages/apps/Car/RotaryController
  • Core est situé dans frameworks/base/core

Historique des coups de pouce

L'OEM peut configurer si chacun des deux types d'historique de poussée est activé ou non et, si c'est le cas, la taille du cache et la politique d'expiration. Tout cela est fait en remplaçant diverses ressources car-ui-library.

Cache de l'historique des focus

( Android 11 QPR3, Android 11 Voiture, Android 12 )
Ce cache FocusArea stocke la vue la plus récemment mise au point dans la FocusArea afin qu'elle puisse être mise au point lorsque vous revenez à la FocusArea . Ce cache peut être configuré en superposant les ressources car-ui-library suivantes :

  • car_ui_focus_history_cache_type :
    1. Le cache est désactivé.
    2. Le cache expirera après un certain temps (voir ci-dessous).
    3. Le cache n'expirera jamais.
  • car_ui_focus_history_expiration_period_ms : combien de millisecondes avant que le cache n'expire si le type de cache est défini sur deux (2) (voir ci-dessus).

Cache de l'historique de la zone de mise au point

( Android 11 QPR3, Android 11 Voiture, Android 12 )
Ce cache stocke un historique des coups de pouce afin que le coup de pouce dans la direction opposée puisse ramener le focus sur le même FocusArea . Ce cache peut être configuré en superposant les ressources car-ui-library suivantes :

  • car_ui_focus_area_history_cache_type :
    1. Le cache est désactivé.
    2. Le cache expire après un certain temps (voir ci-dessous).
    3. Le cache n'expire jamais.
  • car_ui_focus_area_history_expiration_period_ms : combien de millisecondes avant l'expiration du cache si le type de cache est défini sur 2 (voir ci-dessus).
  • car_ui_clear_focus_area_history_when_rotating : Indique s'il faut vider le cache lorsque l'utilisateur tourne le contrôleur.

Rotation

( Android 11 QPR3, Android 11 Voiture, Android 12 )
L'OEM peut remplacer deux ressources entières dans le RotaryService pour spécifier s'il y a une accélération, telle que l'accélération de la souris, pour la rotation :

  • rotation_acceleration_3x_ms : Intervalle de temps (en millisecondes) utilisé pour décider si Google doit accélérer la rotation du contrôleur pour un cran de rotation. Si l'intervalle entre ce cran et le cran de rotation précédent est inférieur à cette valeur, il sera traité comme trois crans de rotation. Réglez-le sur 2147483647 pour désactiver l'accélération 3×.
  • rotation_acceleration_2x_ms : Similaire à rotation_acceleration_3x_ms . Utilisé pour une accélération 2×. Réglez-le sur 2147483647 pour désactiver l'accélération 2×.

L'accélération fonctionne mieux lorsqu'il existe des horodatages individuels pour chaque détente de rotation, comme l' exige le VHAL. Si ceux-ci ne sont pas disponibles, le RotaryService suppose que les crans de rotation sont régulièrement espacés.

/**
     * 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),

Point culminant de la mise au point

L'OEM peut remplacer la surbrillance de focus par défaut dans le framework Android et plusieurs ressources de surbrillance de focus dans car-ui-library.

Mise en surbrillance de la mise au point par défaut

Le framework Android fournit une mise en surbrillance par défaut via l'attribut selectableItemBackground . Dans Theme.DeviceDefault , cet attribut fait référence à item_background.xml dans Core . L'OEM peut superposer item_background.xml pour modifier la surbrillance du focus par défaut.

Ce drawable doit généralement être un StateListDrawable , qui ajuste l'arrière-plan en fonction de différentes combinaisons d'états, y compris android:state_focused et android:state_pressed . Lorsque l'utilisateur utilise le contrôleur rotatif pour focaliser une vue, android:state_focused sera true , mais android:state_pressed sera false . Si l'utilisateur appuie ensuite sur le bouton central du contrôleur rotatif, android:state_focused et android:state_pressed seront true tant que l'utilisateur maintiendra le bouton enfoncé. Lorsque l'utilisateur relâche le bouton, seul android:state_focused restera true .

car-ui-library utilise un thème dérivé de Theme.DeviceDefault . Par conséquent, cette superposition affecte les applications qui utilisent cette bibliothèque et les applications qui utilisent n'importe quel thème dérivé de Theme.DeviceDefault . Cela n'affectera pas les applications qui utilisent un thème sans rapport, tel que Theme.Material .

Focus sur les ressources de mise en évidence dans car-ui-library

L'OEM peut remplacer plusieurs ressources car-ui-library pour contrôler l'apparence de la surbrillance de la mise au point sur les vues avec une surbrillance de mise au point non rectangulaire (telle que ronde ou en forme de pilule) et dans les applications qui utilisent un thème qui ne dérive pas de Theme.DeviceDefault . Ces ressources doivent être superposées afin que la surbrillance de la mise au point soit cohérente avec la surbrillance de la mise au point par défaut pouvant être dessinée.

( Android 11 QPR3, Android 11 Voiture, Android 12 )
Les ressources suivantes sont utilisées pour indiquer quand une vue est focalisée mais pas pressée :

  • car_ui_rotary_focus_fill_color : Couleur de remplissage.
  • car_ui_rotary_focus_stroke_color : Couleur du contour.
  • car_ui_rotary_focus_stroke_width : Épaisseur du contour.

( Android 11 QPR3, Android 11 Voiture, Android 12 )
Les ressources suivantes sont utilisées pour indiquer quand une vue est focalisée et pressée :

  • car_ui_rotary_focus_pressed_fill_color : Couleur de remplissage.
  • car_ui_rotary_focus_pressed_stroke_color : Couleur du contour.
  • car_ui_rotary_focus_pressed_stroke_width : Épaisseur du contour.

Parfois, un bouton est doté d'une couleur d'arrière-plan unie pour attirer l'attention de l'utilisateur, comme dans l'exemple illustré. Cela peut rendre la surbrillance de la mise au point difficile à voir.

Bouton avec fond uni
Figure 2. Bouton avec fond uni

Dans cette situation, le développeur peut spécifier une surbrillance de mise au point personnalisée à l'aide de couleurs secondaires :
  • ( Android 11 QPR3, Android 11 Voiture, 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

Toutes les couleurs peuvent être transparentes et l'une ou l'autre des dimensions peut être nulle si, par exemple, vous vouliez uniquement un remplissage ou uniquement un contour.

Mise en surbrillance de la zone de mise au point

( Android 11 QPR3, Android 11 Voiture, Android 12 )
FocusArea peut dessiner deux types de surbrillance lorsque l'un de ses descendants est focalisé. Les deux peuvent être utilisés conjointement, si vous le souhaitez. Cette fonctionnalité est désactivée par défaut dans AOSP, mais peut être activée en remplaçant les ressources car-ui-library :

  • car_ui_enable_focus_area_foreground_highlight : dessine une surbrillance au-dessus de la FocusArea et de ses descendants. Dans AOSP, ce drawable est un contour autour de la FocusArea . Les OEM peuvent remplacer le car_ui_focus_area_foreground_highlight car_ui_focus_area_foreground_highlight.
  • car_ui_enable_focus_area_background_highlight : dessine une surbrillance au-dessus de la FocusArea mais derrière ses descendants. Dans AOSP, ce drawable est un remplissage uni. Les OEM peuvent remplacer le car_ui_focus_area_background_highlight car_ui_focus_area_background_highlight.

Éditeurs de méthode d'entrée

Les éditeurs de méthode d'entrée (IME) sont des méthodes d'entrée. Par exemple, un clavier à l'écran.

( Android 11 QPR3, Android 11 Voiture, Android 12 )
L'OEM doit superposer la ressource de chaîne default_touch_input_method dans le RotaryService pour spécifier le ComponentName de l'IME tactile. Par exemple, si l'OEM utilise l'IME fourni avec Android Automotive, il doit spécifier com.google.android.apps.automotive.inputmethod/.InputMethodService .

( Android 11 QPR3, Android 11 Voiture, Android 12 )
Si l'OEM a créé un IME spécifiquement pour Rotary, il doit spécifier son ComponentName dans la ressource rotary_input_method . Si cette ressource est superposée, l'IME spécifié est utilisé chaque fois que l'utilisateur interagit avec l'unité principale via le bouton de déplacement, de rotation et central du contrôleur rotatif. Lorsque l'utilisateur touche l'écran, l'IME précédent sera utilisé. Le bouton Retour (et les autres boutons du rotacteur) n'ont aucun effet sur la sélection IME. Si cette ressource n'est pas superposée, aucune commutation IME ne se produit. Carboard ne prend pas en charge le rotatif, de sorte que l'utilisateur ne peut pas saisir de texte via le contrôleur rotatif si l'OEM n'a pas fourni d'IME rotatif.

RotaryIME est un IME rotatif de démonstration. Bien que basique, il suffit d'essayer la commutation automatique IME décrite ci-dessus. Le code source de RotaryIME se trouve dans packages/apps/Car/tests/RotaryIME/ .

Coups de pouce hors écran

Par défaut, lorsque l'utilisateur tente de quitter le bord de l'écran, rien ne se passe. L'OEM peut configurer ce qui doit se produire pour chacune des quatre directions en spécifiant n'importe quelle combinaison de :

  1. Une action globale définie par AccessibilityService . Par exemple, GLOBAL_ACTION_BACK .
  2. Un code clé, tel que KEYCODE_BACK .
  3. Une intention de lancer une activité représentée sous la forme d'une URL.

( Android 11 QPR3, Android 11 Voiture, Android 12 )
Celles-ci sont spécifiées en superposant les ressources de tableau suivantes dans le RotaryService :

  • off_screen_nudge_global_actions : tableau d'actions globales à effectuer lorsque l'utilisateur pousse vers le haut, le bas, la gauche ou la droite du bord de l'écran. Aucune action globale n'est effectuée si l'élément concerné de ce tableau est -1.
  • off_screen_nudge_key_codes : tableau des codes clés des événements de clic à injecter lorsque l'utilisateur pousse vers le haut, le bas, la gauche ou la droite du bord de l'écran. Aucun événement n'est injecté si l'élément concerné de ce tableau est 0 ( KEYCODE_UNKNOWN ).
  • off_screen_nudge_intents : tableau d'intentions pour lancer une activité lorsque l'utilisateur pousse vers le haut, le bas, la gauche ou la droite du bord de l'écran. Aucune activité n'est lancée si l'élément concerné de ce tableau est vide.

Autres configurations

Vous devez superposer les ressources RotaryService suivantes :

  • ( Android 11 QPR3, Android 11 Voiture, Android 12 )
    config_showHeadsUpNotificationOnBottom : valeur booléenne indiquant si les notifications d'avertissement doivent être affichées en bas plutôt qu'en haut. Cela doit avoir la même valeur que la ressource booléenne config_showHeadsUpNotificationOnBottom dans frameworks/base/packages/CarSystemUI/res/values/config.xml
  • ( Android 11 QPR3, Android 11 Voiture, Android 12 )
    notification_headsup_card_margin_horizontal : Marges gauche et droite pour la fenêtre de notification tête haute. Cela doit avoir la même valeur que la ressource notification_headsup_card_margin_horizontal dimension dans packages/apps/Car/Notification/res/values/dimens.xml
  • ( Android 12 )
    excluded_application_overlay_window_titles : un tableau de titres de fenêtres qui ne doivent pas être considérées comme des fenêtres superposées. Cela devrait inclure les titres des fenêtres d'application qui représentent TaskViews ou TaskDisplayAreas . Par défaut, cette liste ne contient que "Maps".

Vous pouvez superposer la ressource RotaryService suivante :

  • ( Android 11 QPR3, Android 11 Voiture, Android 12 )
    long_press_ms : valeur entière représentant le nombre de millisecondes pendant lesquelles le bouton central doit être maintenu enfoncé pour déclencher un appui long. Zéro indique que le délai d'attente d'appui long par défaut du système doit être utilisé. Ceci est la valeur par défault.