Guide d'intégration pour les OEM

Cette page explique comment traiter les entrées par dispositif rotatif dans le VHAL, configurer votre build d'inclure le service rotatif et de personnaliser son fonctionnement dans toutes les applications. Pour les applications OEM préinstallées, telles que le lanceur d'applications fourni par l'OEM, consultez Bibliothèque Car UI (car-ui-library).

VHAL

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

  • Déplacer vers le haut, le bas, la gauche et la droite.
  • Faites pivoter la vue 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 Retour.
  • Appuyez sur le bouton d'accueil.
  • Appuyez sur les autres boutons, comme Téléphone et Multimédia.

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

Le VHAL doit gérer les actions suivantes:

Coup de pouce

Lorsque l'utilisateur pousse le contrôleur rotatif vers la droite, le VHAL doit utiliser le la propriété HW_KEY_INPUT avec le int32Values suivant pour envoyer une vers 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 code de clavier avec ACTION_UP. Pour les encouragements dans d'autres directions, utilisez codes de clavier correspondants.

Il n'y a pas de codes de clavier pour les diagonales, mais le VHAL peut combiner un format horizontal et vertical pour produire une diagonale si le matériel prend en charge les diagonales. Par exemple, encourager et celui de 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 des ordres, puis en relâchant le contrôleur rotatif, vous devriez obtenir:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

L'utilisateur peut pousser le contrôleur rotatif vers la perpendiculaire avant de le relâcher. Prenons l'exemple du scénario suivant:

Direction perpendiculaire
Figure 1. Direction perpendiculaire

La séquence d'événements suivante devrait être générée:

  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 repeat ne doit être généré lorsque le contrôleur rotatif est maintenu dans un sens.

Faire pivoter

Lorsque l'utilisateur fait pivoter le contrôleur rotatif d'un point (clic) dans le sens des aiguilles d'une montre, le VHAL doit utiliser la propriété HW_ROTARY_INPUT avec l'élément int32Values suivant : pour envoyer un événement à Android:

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

Le code temporel de l'événement doit être défini sur le temps écoulé en nanosecondes.

Une rotation d'un (1) retrait dans le sens inverse des aiguilles d'une montre devrait générer le même événement, mais avec -1 pour le nombre de retraits.

Si plusieurs dents de rotation dans la même direction se succèdent rapidement, le VHAL doivent combiner les retenues en un seul événement afin de ne pas surcharger le système d'événements. Dans ce cas, l'horodatage de l'événement doit correspondre au moment où le premier arrêt de rotation s'est produit. Le champ int32Values doit inclure le nombre de nanosecondes entre les retenues consécutives. de rotation.

Par exemple, la séquence de rotations suivante:

  • À l'instant t0, l'utilisateur a effectué une rotation d'un cran dans le sens inverse des aiguilles d'une montre.
  • À l'instant t0 + 5 ns, l'utilisateur a effectué une rotation d'un cran dans le sens inverse des aiguilles d'une montre.
  • À l'instant t0 + 8 ns, l'utilisateur a effectué une rotation d'un cran dans le sens inverse des aiguilles d'une montre.

doit générer l'événement suivant:

  • Propriété: HW_ROTARY_INPUT
  • Code temporel: t0
  • int32Values:
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (trois pressions dans le sens inverse des aiguilles d'une montre).
    3. Affichage cible.
    4. 5 ns entre le premier et le deuxième creux.
    5. 3 ns entre le deuxième et le troisième point d'arrêt.

Bouton central

Lorsque l'utilisateur appuie sur le bouton central, le VHAL doit utiliser HW_KEY_INPUT avec le int32Values suivant 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 code de clavier avec ACTION_UP.

Ne générez pas d'événements repeat lorsque vous maintenez le bouton central enfoncé.

Bouton Retour

Lorsque l'utilisateur appuie sur le bouton "Retour", le VHAL doit utiliser HW_KEY_INPUT avec le int32Values suivant 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 code de clavier avec ACTION_UP.

Aucun événement repeat ne doit être généré lorsque le bouton central est enfoncé.

Bouton Accueil

Gérez le bouton d'accueil comme vous le feriez pour le bouton "Retour", mais avec KEYCODE_HOME à la place sur KEYCODE_BACK.

Autres boutons

Si le contrôleur rotatif inclut des boutons supplémentaires, le VHAL peut les gérer aime l'OEM, car ils ne sont pas considérés comme faisant partie du dispositif 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 de clavier différents. Exemples : KEYCODE_CALL ou KEYCODE_MUSIC.

Configuration de compilation

La navigation par dispositif rotatif 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:

  • RotaryPlayground Application de référence pour le dispositif rotatif (voir RotaryPlayground).
  • RotaryIME IME rotatif de démonstration (voir Éditeurs de mode de saisie).
  • CarRotaryImeRRO : superposition de RotaryIME.

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

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

Personnalisation

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

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

Historique des rappels automatiques

L'OEM peut configurer l'activation ou non de chacun des deux types d'historique des rappels automatiques, et, le cas échéant, la taille du cache et la règle d'expiration. Pour cela, il suffit de remplacer ressources.

Placer le curseur sur le cache de l'historique

(Android 11 QPR3, Android 11 Car, Android 12)
Ce cache par FocusArea stocke la dernière vue sélectionnée dans le FocusArea afin qu'il puisse être sélectionné lorsque vous revenez à 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 expire au bout d'un certain temps (voir ci-dessous).
    3. Le cache n'expirera jamais.
  • car_ui_focus_history_expiration_period_ms: nombre de millisecondes avant l'événement Le cache expire si le type de cache est défini sur deux (2) (voir ci-dessus).

Cache de l'historique FocusArea

(Android 11 QPR3, Android 11 Car, Android 12)
Ce cache stocke un historique des rappels automatiques afin que ceux dans la direction opposée puissent replacer le curseur sur le même FocusArea. Ce cache peut être configuré en superposant le ressources car-ui-library suivantes:

  • car_ui_focus_area_history_cache_type:
    1. Le cache est désactivé.
    2. Le cache expire au bout d'un certain temps (voir ci-dessous).
    3. Le cache n'expire jamais.
  • car_ui_focus_area_history_expiration_period_ms: nombre de millisecondes avant le début de l'événement le cache expire si le type de cache est défini sur 2 (voir ci-dessus).
  • car_ui_clear_focus_area_history_when_rotating: indique si le cache doit être vidé ou non. lorsque l'utilisateur fait pivoter la manette.

Rotation

(Android 11 QPR3, Android 11 Car, Android 12)
L'OEM peut remplacer deux ressources d'entiers dans RotaryService pour spécifier si la rotation entraîne une accélération, telle que l'accélération du curseur:

  • rotation_acceleration_3x_ms: intervalle de temps (en millisecondes) utilisé pour décider si Google doit accélérer la rotation de la manette pour obtenir un blocage de rotation. Si le l'intervalle entre ce cran et le précédent est inférieur à cette valeur, on considère qu'il y a trois points de rotation. Définissez cette valeur sur 2147483647 pour désactiver 3 fois de l'accélération matérielle.
  • rotation_acceleration_2x_ms: semblable à rotation_acceleration_3x_ms. Utilisé pour l'accélération × 2. Définissez cette valeur sur 2147483647 pour désactiver l'accélération 2×.

L'accélération fonctionne mieux avec des codes temporels individuels pour chaque retenue de la rotation, obligatoire par le VHAL. Si elles ne sont pas disponibles, le RotaryService suppose que les retenues de de rotation sont espacés uniformément.

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

Sélectionner la sélection

L'OEM peut ignorer la mise en surbrillance par défaut dans le framework Android et plusieurs ressources mettent en évidence les ressources dans car-ui-library.

Mise en surbrillance par défaut du focus

Le framework Android met en évidence par défaut l'attribut selectableItemBackground Dans Theme.DeviceDefault, ce fait référence à item_background.xml dans Core. L'OEM peut superposer item_background.xml pour modifier le drawable de mise en surbrillance par défaut du focus.

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 sélectionner 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, à la fois android:state_focused et android:state_pressed sera true lorsque l'utilisateur maintiendra le bouton enfoncé. Lorsque l'utilisateur relâche le bouton, il ne reste que android:state_focused. 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 celles 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, comme Theme.Material.

Placer le curseur sur les ressources de la bibliothèque car-ui-library

L'OEM peut ignorer plusieurs ressources car-ui-library pour contrôler la mise en surbrillance regarde les vues dont la mise en surbrillance n'est pas rectangulaire (arrondie ou en forme de pilule, par exemple). Applications dont le thème ne provient pas de Theme.DeviceDefault. Ces les ressources doivent être superposées de sorte que l'accent soit cohérent avec Drawable mise en surbrillance par défaut.

(Android 11 QPR3, Android 11 Car, Android 12)
Les ressources suivantes sont utilisées pour indiquer quand une vue est sélectionnée mais pas appuyé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 Car, Android 12)
Les ressources suivantes sont utilisées pour indiquer si une vue est sélectionnée et si vous appuyez dessus:

  • 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 se voit attribuer une couleur d'arrière-plan unie pour attirer l'attention de l'utilisateur, comme dans l'exemple présenté ici. La mise en surbrillance de l'élément peut alors être difficile à voir.

Bouton avec un arrière-plan uni
Figure 2. Bouton avec un arrière-plan uni

Dans ce cas, le développeur peut spécifier une mise en surbrillance personnalisée à l'aide de couleurs secondaires: <ph type="x-smartling-placeholder">
    </ph>
  • (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

Toutes les couleurs peuvent être transparentes et les deux peuvent être égales à zéro si, par exemple, voulait seulement un remplissage ou seulement un contour.

Sélection de FocusArea

(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea peut dessiner deux types de mise en surbrillance lorsque l'un de ses descendants est concentré. Vous pouvez les utiliser 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: tracez une mise en surbrillance sur le FocusArea et ses descendants. Dans AOSP, ce drawable est un contour autour du FocusArea. Les OEM peuvent ignorer Drawable car_ui_focus_area_foreground_highlight.
  • car_ui_enable_focus_area_background_highlight: tracez une mise en surbrillance au-dessus du FocusArea, mais derrière ses descendants. Dans AOSP, ce drawable est un remplissage solide. Les OEM peuvent ignorer le drawable car_ui_focus_area_background_highlight.

Éditeurs du mode de saisie

Les éditeurs de mode de saisie (IME) sont des modes de saisie. Par exemple, un clavier à l'écran.

(Android 11 QPR3, Android 11 Car, Android 12)
L'OEM doit superposer la ressource de chaîne default_touch_input_method. dans le RotaryService pour spécifier le ComponentName un IME basé sur l'écran 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 Car, Android 12)
Si l'OEM a créé un IME spécifiquement pour le dispositif rotatif, il doit spécifier son ComponentName dans la ressource rotary_input_method. Si cette ressource est superposé, l'IME spécifié est utilisé chaque fois que l'utilisateur interagit avec l'unité principale. via le bouton de rappel, la rotation et le bouton 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 cadran contrôleur) n'ont aucun effet sur la sélection de l'IME. Si cette ressource n'est pas superposée, aucun changement d'IME se produit. Carboard n'est pas compatible avec le dispositif rotatif, de sorte que l'utilisateur ne peut pas saisir de texte via ce dispositif. contrôleur si l'OEM n'a pas fourni d'IME rotatif.

RotaryIME est un IME rotatif de démonstration. Bien que basique, il suffit de essayez le basculement automatique IME décrit ci-dessus. Le code source de RotaryIME se trouve dans packages/apps/Car/tests/RotaryIME/.

Rappels automatiques hors écran

Par défaut, rien ne se passe lorsque l'utilisateur essaie de sortir du bord de l'écran. L'OEM peut configurer ce qui doit se passer pour chacune des quatre directions en spécifiant combinaison de:

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

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

  • off_screen_nudge_global_actions: tableau des actions globales à effectuer lorsque l'utilisateur pousse l'utilisateur vers le haut, le bas, la gauche ou la droite du bord de l'écran. Aucune action globale n'est si l'élément pertinent de ce tableau est -1.
  • off_screen_nudge_key_codes: tableau des codes de touches des événements de clic à injecter lorsque l'utilisateur pousse le doigt vers le haut, le bas, la gauche ou la droite du bord de l'écran. Aucun événement injecté si l'élément concerné de ce tableau est 0 (KEYCODE_UNKNOWN).
  • off_screen_nudge_intents: tableau d'intents pour lancer une activité lorsque l'utilisateur pousse l'utilisateur 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 pertinent de ce tableau est vide.

Autres configurations

Vous devez superposer les ressources RotaryService suivantes:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    config_showHeadsUpNotificationOnBottom: valeur booléenne indiquant si les notifications prioritaires doivent être affichées en bas et non en haut. Cela doit ont la même valeur que config_showHeadsUpNotificationOnBottom ; Ressource booléenne dans frameworks/base/packages/CarSystemUI/res/values/config.xml
  • (Android 11 QPR3, Android 11 Car, Android 12)
    notification_headsup_card_margin_horizontal: marges gauche et droite de ou une fenêtre de notification prioritaire. Il doit avoir la même valeur que notification_headsup_card_margin_horizontal ressource de luminosité dans packages/apps/Car/Notification/res/values/dimens.xml
  • (Android 12)
    excluded_application_overlay_window_titles: tableau de des fenêtres qui ne doivent pas être considérées comme des fenêtres en superposition. Cela doit inclure les titres des fenêtres d'application représentant TaskViews ou TaskDisplayAreas. Par défaut, cette liste ne contient que "Cartes".

Vous pouvez superposer la ressource RotaryService suivante:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    long_press_ms: valeur entière représentant le nombre de millisecondes qu'une Vous devez maintenir le bouton central enfoncé pour déclencher un appui prolongé. Le chiffre 0 indique que le système le délai par défaut d'appui prolongé doit être utilisé. Il s'agit de la valeur par défaut.