API du groupe d'instruments

Utilisez l'API Instrument Cluster (une API Android) pour afficher les applications de navigation, y compris Google Maps, sur un écran secondaire dans une voiture, par exemple derrière le volant du tableau de bord. Cette page décrit comment créer un service pour contrôler cet affichage secondaire, puis intégrer le service à CarService afin que les applications de navigation puissent afficher une interface utilisateur.

Terminologie

Les termes suivants sont utilisés sur cette page :

Terme Description
CarInstrumentClusterManager Une instance CarManager qui permet aux applications externes de lancer une activité sur le groupe d'instruments et de recevoir des rappels lorsque le groupe d'instruments est prêt à afficher des activités.
CarManager Classe de base de tous les gestionnaires utilisés par les applications externes pour interagir avec les services spécifiques à la voiture implémentés par CarService .
CarService Service de plate-forme Android qui assure la communication entre les applications externes (y compris Google Maps) et les fonctionnalités spécifiques à la voiture, telles que l'accès au groupe d'instruments.
Destination La destination finale vers laquelle le véhicule naviguera.
ETA Heure estimée d'arrivée à destination.
Unité principale (HU) Unité de calcul primaire embarquée dans une voiture. Le HU exécute tout le code Android et est connecté à l’écran central de la voiture.
Groupe d'instruments Écran secondaire situé derrière le volant et entre les instruments de la voiture. Il peut s'agir d'une unité de calcul indépendante connectée au HU via le réseau interne de la voiture (bus CAN) ou d'un écran secondaire connecté au HU.
InstrumentClusterRenderingService Classe de base pour le service utilisé pour s'interfacer avec l'affichage du groupe d'instruments. Les OEM doivent fournir une extension de cette classe qui interagit avec le matériel spécifique à l'OEM.
Application KitchenSink Application de test incluse avec Android Automotive.
Itinéraire Un chemin spécifique le long duquel un véhicule navigue pour arriver à une destination.
Service simple Un service Android avec l'attribut android:singleUser . À tout moment, au plus une instance du service s'exécute sur le système Android.

Conditions préalables

Pour développer l’intégration, assurez-vous d’avoir ces éléments :

  • Environnement de développement Android. Pour configurer l'environnement de développement Android, consultez Exigences de build .
  • Téléchargez le code source Android. Obtenez la dernière version du code source Android depuis la branche pi-car-release (ou version ultérieure) sur https://android.googlesource.com .
  • Unité principale (HU). Un appareil Android capable d'exécuter Android 9 (ou version ultérieure). Cet appareil doit avoir son propre écran et être capable de faire clignoter l'écran avec les nouvelles versions d'Android.
  • Le groupe d'instruments est l'un des éléments suivants :
    • Écran secondaire physique attaché au HU. Si le matériel et le noyau de l'appareil prennent en charge la gestion de plusieurs écrans.
    • Unité indépendante. Toute unité de calcul connectée au HU via une connexion réseau, capable de recevoir et d'afficher un flux vidéo sur son propre écran.
    • Affichage émulé. Pendant le développement, vous pouvez utiliser l'un de ces environnements émulés :
      • Affichages secondaires simulés. Pour activer un affichage secondaire simulé sur n'importe quelle distribution AOSP Android, accédez aux paramètres Options du développeur dans l'application système Paramètres, puis sélectionnez Simuler les affichages secondaires. Cette configuration équivaut à fixer un écran secondaire physique, avec la limitation que cet écran est superposé à l'écran principal.
      • Groupe d'instruments émulé. L'émulateur Android inclus avec Android Automotive offre une option permettant d'afficher un groupe d'instruments avec le service ClusterRenderingService connecté à l'écran secondaire.
      • émulateur _qemu-pipes . Le service ClusterRenderingService est connecté à l’affichage secondaire. implémentation du groupe d'instruments de référence pour se connecter à cet écran externe émulé.

Architecture d'intégration

Composants d'intégration

Toute intégration de l'API Instrument Cluster se compose de ces trois composants :

  • CarService
  • Applications de navigation
  • Service de groupe d'instruments OEM

Composants d'intégration

Service automobile

CarService sert d'intermédiaire entre les applications de navigation et la voiture, garantissant qu'une seule application de navigation est active à un moment donné et que seules les applications disposant de l'autorisation android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL peuvent envoyer des données à la voiture.

CarService démarre tous les services spécifiques à la voiture et donne accès à ces services via une série de gestionnaires. Pour interagir avec les services, les applications exécutées dans la voiture peuvent accéder à ces gestionnaires.

Pour la mise en œuvre du groupe d'instruments, les constructeurs automobiles doivent créer une implémentation personnalisée d'InstrumentClusterRendererService et mettre à jour le service ClusterRenderingService connecté à l'écran secondaire.

Lors du rendu d'un groupe d'instruments, pendant le processus de démarrage, le CarService lit la clé InstrumentClusterRendererService du service ClusterRenderingService qui est connecté à l'écran secondaire. pour localiser une implémentation de InstrumentClusterService . Dans AOSP, cette entrée pointe vers l’exemple de service de rendu d’implémentation de cluster de l’API Navigation State :

<string name="instrumentClusterRendererService">
android.car.cluster/.ClusterRenderingService
</string>

Le service mentionné dans cette entrée est initialisé et lié à CarService . Lorsque des applications de navigation, comme Google Maps, demandent un CarInstrumentClusterManager , CarService fournit un gestionnaire qui met à jour l'état du cluster d'instruments à partir du InstrumentClusterRenderingService lié. (Dans ce cas, lié fait référence aux services Android .)

Service du groupe d'instruments

Les OEM doivent créer un package Android (APK) contenant une sous-classe du service ClusterRenderingService connecté à l’affichage secondaire. Le service ClusterRenderingService est connecté à l’affichage secondaire. pour un échantillon.

Cette classe répond à deux objectifs :

  • Fournit une interface Android et le dispositif de rendu Instrument Cluster (le but de cette page).
  • Reçoit et restitue des mises à jour de l'état de navigation, telles que le guidage de navigation étape par étape.

Pour le premier objectif, les implémentations OEM de InstrumentClusterRendererService doivent initialiser l'affichage secondaire utilisé pour restituer les informations sur les écrans de l'habitacle de la voiture et communiquer ces informations à CarService en appelant les méthodes InstrumentClusterRendererService.setClusterActivityOptions() et InstrumentClusterRendererService.setClusterActivityState() .

Pour la deuxième fonction, le service Instrument Cluster doit fournir une implémentation du service ClusterRenderingService connecté à l'écran secondaire. interface qui reçoit les événements de mise à jour de l'état de navigation, qui sont codés en tant que eventType et les données d'événement codées dans un bundle.

Séquence d'intégration

Le diagramme suivant illustre l'implémentation d'un état de navigation qui restitue les mises à jour :

Séquence d'intégration

Dans cette illustration, les couleurs désignent les éléments suivants :

  • Jaune. CarService et CarNavigationStatusManager fournis par la plateforme Android. Pour en savoir plus, consultez Car et CAR_NAVIGATION_SERVICE .
  • Cyan. InstrumentClusterRendererService implémenté par l'OEM.
  • Violet. L'application de navigation mise en œuvre par Google et des développeurs tiers.
  • Vert. CarAppFocusManager . Pour en savoir plus, consultez Utilisation de l'API CarAppFocusManager ci-dessous et CarAppFocusManager .

Le flux d’informations sur l’état de navigation suit cette séquence :

  1. CarService initialise le InstrumentClusterRenderingService .
  2. Lors de l'initialisation, InstrumentClusterRenderingService met à jour CarService avec :
    1. Propriétés d'affichage du groupe d'instruments, telles que les limites non obscurcies (voir plus de détails sur les limites non obscurcies plus tard).
    2. Options d'activité nécessaires pour lancer des activités dans l'affichage du groupe d'instruments (voir plus de détails sur ActivityOptions .
  3. Une application de navigation (telle que Google Maps pour Android Automotive ou toute application de cartes disposant des autorisations requises) :
    1. Obtient un CarAppFocusManager en utilisant la classe Car de car-lib.
    2. Avant le début des instructions détaillées, appels à CarAppFocusManager.requestFocus() pour transmettre CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION comme paramètre appType .
  4. CarAppFocusManager communique cette demande à CarService . Si cela est accordé, CarService inspecte le package de l'application de navigation et localise une activité marquée avec la catégorie android.car.cluster.NAVIGATION .
  5. Si elle est trouvée, l'application de navigation utilise les ActivityOptions signalées par InstrumentClusterRenderingService pour lancer l'activité et inclut les propriétés d'affichage du groupe d'instruments en tant qu'extras dans l'intention.

Intégrer l'API

L'implémentation InstrumentClusterRenderingService doit :

  • Soyez désigné comme service singleton en ajoutant la valeur suivante au fichier AndroidManifest.xml. Cela est nécessaire pour garantir qu'une seule copie du service Instrument Cluster s'exécute, même pendant l'initialisation et le changement d'utilisateur :
    android:singleUser="true"
  • Détenez l’autorisation système BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE . Cela garantit que seul le service de rendu du groupe d'instruments inclus dans l'image système Android est toujours lié par CarService :
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Implémenter InstrumentClusterRenderingService

Pour créer le service :

  1. Écrivez une classe qui s'étend du service ClusterRenderingService et est connectée à l'affichage secondaire.
  2. puis ajoutez une entrée correspondante à votre fichier AndroidManifest.xml . Cette classe contrôle l'affichage du groupe d'instruments et peut ( en option ) restituer les données de l'API d'état de navigation.
  3. Pendant onCreate() , utilisez ce service pour initialiser la communication avec le matériel de rendu. Les options incluent :
    • Déterminez l’affichage secondaire à utiliser pour le groupe d’instruments.
    • Créez un affichage virtuel afin que l'application Instrument Cluster restitue et transmette l'image rendue à une unité externe (en utilisant un format de streaming vidéo, tel que H.264).
  4. Lorsque l'affichage indiqué ci-dessus est prêt, ce service doit appeler InstrumentClusterRenderingService#setClusterActivityLaunchOptions() pour définir les ActivityOptions exactes qui doivent être utilisées pour afficher une activité sur le cluster d'instruments. Utilisez ces paramètres :
    • catégorie. Le service ClusterRenderingService est connecté à l’affichage secondaire.
    • ActivityOptions. Une instance ActivityOptions qui peut être utilisée pour lancer une activité dans le cluster d'instruments. Par exemple, à partir de l'exemple d'implémentation d'Instrument Cluster sur AOSP :
      getService().setClusterActivityLaunchOptions(
         CATEGORY_NAVIGATION,
         ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  5. Lorsque le cluster d'instruments est prêt à afficher les activités, ce service doit appeler InstrumentClusterRenderingService#setClusterActivityState() . Utilisez ces paramètres :
    • Le service category ClusterRenderingService est connecté à l’affichage secondaire.
    • Le bundle state généré avec le service ClusterRenderingService est connecté à l'affichage secondaire.
    • Assurez-vous de fournir les données suivantes :
      • visible Spécifie le groupe d'instruments comme étant visible et prêt à afficher le contenu.
      • unobscuredBounds Un rectangle qui définit la zone de l'affichage du groupe d'instruments dans laquelle il est possible d'afficher du contenu en toute sécurité. Par exemple, les zones couvertes par des cadrans et des jauges.
  6. Remplacez la méthode Service#dump() et signalez les informations d'état utiles pour le débogage (voir dumpsys pour plus d'informations).

Exemple d’implémentation d’InstrumentClusterRenderingService

L'exemple suivant décrit une implémentation InstrumentClusterRenderingService , qui crée un VirtualDisplay pour présenter le contenu du cluster d'instruments sur un écran physique distant.

Alternativement, ce code pourrait transmettre le displayId d’un affichage secondaire physique connecté au HU, s’il est connu qu’il en existe un.

/**
* Sample {@link InstrumentClusterRenderingService} implementation
*/
public class SampleClusterServiceImpl extends InstrumentClusterRenderingService {
   // Used to retrieve or create displays
   private final DisplayManager mDisplayManager;
   // Unique identifier for the display to be used for instrument
   // cluster
   private final String mUniqueId = UUID.randomUUID().toString();
   // Format of the instrument cluster display
   private static final int DISPLAY_WIDTH = 1280;
   private static final int DISPLAY_HEIGHT = 720;
   private static final int DISPLAY_DPI = 320;
   // Area not covered by instruments
   private static final int DISPLAY_UNOBSCURED_LEFT = 40;
   private static final int DISPLAY_UNOBSCURED_TOP = 0;
   private static final int DISPLAY_UNOBSCURED_RIGHT = 1200;
   private static final int DISPLAY_UNOBSCURED_BOTTOM = 680;
   @Override
   public void onCreate() {
      super.onCreate();
      // Create a virtual display to render instrument cluster activities on
      mDisplayManager = getSystemService(DisplayManager.class);
      VirtualDisplay display = mDisplayManager.createVirtualDisplay(
          mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null,
          0 /* flags */, null, null);
      // Do any additional initialization (e.g.: start a video stream
      // based on this virtual display to present activities on a remote
      // display).
      onDisplayReady(display.getDisplay());
}
private void onDisplayReady(Display display) {
    // Report activity options that should be used to launch activities on
    // the instrument cluster.
    String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION;
    ActionOptions options = ActivityOptions.makeBasic()
        .setLaunchDisplayId(display.getDisplayId());
    setClusterActivityOptions(category, options);
    // Report instrument cluster state.
    Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT,
        DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT,
        DISPLAY_UNOBSCURED_BOTTOM);
    boolean visible = true;
    ClusterActivityState state = ClusterActivityState.create(visible,
       unobscuredBounds);
    setClusterActivityState(category, options);
  }
}

Utilisez l'API CarAppFocusManager

L'API CarAppFocusManager fournit une méthode nommée getAppTypeOwner() , qui permet au service de cluster écrit par les OEM de savoir quelle application de navigation a le focus de navigation à un moment donné. Les OEM peuvent utiliser la méthode CarAppFocusManager#addFocusListener() existante, puis utiliser getAppTypeOwner() pour savoir quelle application a le focus. Grâce à ces informations, les OEM peuvent :

  • Basculez l’activité affichée dans le cluster vers l’activité de cluster fournie par l’application de navigation détenant le focus.
  • Peut détecter si l'application de navigation ciblée a une activité de cluster ou non. Si l'application de navigation ciblée n'a pas d'activité de cluster (ou si cette activité est désactivée), les constructeurs OEM peuvent envoyer ce signal au DIM de la voiture afin que la facette de navigation du cluster soit complètement ignorée.

Utilisez CarAppFocusManager pour définir et écouter le focus actuel de l'application, comme la navigation active ou une commande vocale. Habituellement, une seule instance d’une telle application est activement exécutée (ou ciblée) dans le système.

Utilisez la méthode CarAppFocusManager#addFocusListener(..) pour écouter les changements de focus de l'application :

import android.car.CarAppFocusManager;

...

Car car = Car.createCar(this);
mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE);
mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);

...

public void onAppFocusChanged(int appType, boolean active) {
    // Use the CarAppFocusManager#getAppTypeOwner(appType) method call
    // to retrieve a list of active package names
}

Utilisez la méthode CarAppFocusManager#getAppTypeOwner(..) pour récupérer les noms de package du propriétaire actuel d’un type d’application donné qui est sélectionné. Cette méthode peut renvoyer plusieurs noms de package si le propriétaire actuel utilise la fonctionnalité android:sharedUserId .

import android.car.CarAppFocusManager;

...

Car car = Car.createCar(this);
mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE);
List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner(
              CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);

if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) {
        // No Navigation app has focus
        // OEM may choose to show their default cluster view
} else {
       // focusOwnerPackageNames
       // Use the PackageManager to retrieve the cluster activity for the package(s)
       // returned in focusOwnerPackageNames
}

...

Annexe : Utiliser l'exemple d'application

AOSP fournit un exemple d'application qui implémente l'API Navigation State.

Pour exécuter cet exemple d'application :

  1. Créez et flashez Android Auto sur un HU pris en charge. Utilisez les instructions de création et de clignotement Android spécifiques à votre appareil. Pour obtenir des instructions, voir Utilisation des tableaux de référence .
  2. Connectez un écran secondaire physique au HU (si pris en charge) ou allumez le HU secondaire virtuel :
    1. Sélectionnez Mode développeur dans l'application Paramètres.
    2. Accédez à Paramètres > Système > Avancé > Options du développeur > Simuler les affichages secondaires .
  3. Redémarrez le HU. Le service ClusterRenderingService est connecté à l'affichage secondaire.
  4. Pour lancer l'application KitchenSink :
    1. Ouvrez le tiroir.
    2. Allez dans Inst. Grappe .
    3. Cliquez sur DÉMARRER LES MÉTADONNÉES .

KitchenSink demande le focus NAVIGATION, qui demande au service DirectRenderingCluster d'afficher une interface utilisateur simulée sur le groupe d'instruments.