Kombiinstrument

Verwenden Sie die Instrument Cluster API (eine Android-API), um Navigations-Apps, einschließlich Google Maps, auf einem sekundären Display in einem Auto anzuzeigen, z. B. hinter dem Lenkrad auf der Instrumententafel. Auf dieser Seite wird beschrieben, wie Sie einen Dienst erstellen, um diese sekundäre Anzeige zu steuern, und den Dienst dann in CarService integrieren, damit Navigations-Apps eine Benutzeroberfläche anzeigen können.

Terminologie

Auf dieser Seite werden folgende Begriffe verwendet:

Begriff Beschreibung
CarInstrumentClusterManager Ein CarManager , der es externen Apps ermöglicht, eine Aktivität auf dem Kombiinstrument zu starten und Rückrufe zu erhalten, wenn das Kombiinstrument bereit ist, Aktivitäten anzuzeigen.
AutoManager Basisklasse aller Manager, die von externen Apps verwendet werden, um mit von CarService implementierten CarService Diensten zu interagieren.
CarService Android-Plattformdienst, der die Kommunikation zwischen externen Apps (einschließlich Google Maps) und fahrzeugspezifischen Funktionen wie dem Zugriff auf das Kombiinstrument bereitstellt.
Ziel Das endgültige Ziel, zu dem das Fahrzeug navigiert.
Voraussichtliche Ankunftszeit Geschätzte Ankunftszeit am Zielort.
Haupteinheit (HU) Primäre Recheneinheit eingebettet in ein Auto. Die HU führt alle Android-Codes aus und ist mit dem zentralen Display im Auto verbunden.
Kombiinstrument Zweitanzeige hinter dem Lenkrad und zwischen den Fahrzeuginstrumenten. Dies kann eine unabhängige Recheneinheit sein, die über das interne Netzwerk des Fahrzeugs (CAN-Bus) mit der HU verbunden ist, oder ein sekundäres Display, das an die HU angeschlossen ist.
InstrumentClusterRenderingService Basisklasse für den Dienst, der als Schnittstelle mit der Anzeige des Instrumentenclusters verwendet wird. OEMs müssen eine Erweiterung dieser Klasse bereitstellen, die mit der OEM-spezifischen Hardware interagiert.
KitchenSink-App Testanwendung in Android Automotive enthalten.
Route Ein bestimmter Weg, auf dem ein Fahrzeug navigiert, um an ein Ziel zu gelangen.
Singleton-Dienst Ein Android-Dienst mit dem Attribut android:singleUser . Zu jedem Zeitpunkt läuft höchstens eine Instanz des Dienstes auf dem Android-System.

Voraussetzungen

Um die Integration zu entwickeln, stellen Sie sicher, dass diese Elemente vorhanden sind:

  • Android-Entwicklungsumgebung. Informationen zum Einrichten der Android-Entwicklungsumgebung finden Sie unter Build-Anforderungen .
  • Laden Sie den Android-Quellcode herunter. Holen Sie sich die neueste Version des Android-Quellcodes aus dem pi-car-release-Zweig (oder höher) unter https://android.googlesource.com .
  • Haupteinheit (HU). Ein Android-Gerät, auf dem Android 9 (oder höher) ausgeführt werden kann. Dieses Gerät muss über ein eigenes Display verfügen und in der Lage sein, das Display mit neuen Builds von Android zu flashen.
  • Kombiinstrument ist eines der folgenden:
    • Physische Sekundäranzeige, die an der HU angebracht ist. Wenn die Gerätehardware und der Kernel die Verwaltung mehrerer Displays unterstützen.
    • Unabhängige Einheit. Jede über eine Netzwerkverbindung mit der HU verbundene Recheneinheit, die in der Lage ist, einen Videostream zu empfangen und auf einem eigenen Display anzuzeigen.
    • Emulierte Anzeige. Während der Entwicklung können Sie eine dieser emulierten Umgebungen verwenden:
      • Simulierte Sekundäranzeigen. Um eine simulierte Sekundäranzeige auf einer beliebigen AOSP-Android-Distribution zu aktivieren, gehen Sie zu den Einstellungen für Entwickleroptionen in der Systemanwendung „Einstellungen“ und wählen Sie dann Sekundäranzeigen simulieren aus. Diese Konfiguration entspricht dem Anbringen eines physischen sekundären Displays, mit der Einschränkung, dass dieses Display das primäre Display überlagert.
      • Emuliertes Kombiinstrument. Der in Android Automotive enthaltene Android-Emulator bietet eine Option zum Anzeigen eines Kombiinstruments mit dem Android-Emulator _qemu-pipes . Verwenden Sie die DirectRenderingCluster- Referenz-Instrumentencluster-Implementierung, um eine Verbindung zu dieser emulierten externen Anzeige herzustellen.

Integrationsarchitektur

Integrationskomponenten

Jede Integration der Instrument Cluster API besteht aus diesen drei Komponenten:

  • CarService
  • Navigations-Apps
  • OEM-Instrumentencluster-Service

Integrationskomponenten

Autowerkstatt

CarService vermittelt zwischen Navigations-Apps und dem Auto und stellt sicher, dass immer nur eine Navigations-App aktiv ist und nur Apps mit der android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL Daten an das Auto senden können.

CarService alle autospezifischen Dienste und bietet Zugriff auf diese Dienste über eine Reihe von Managern. Um mit den Diensten zu interagieren, können im Auto laufende Anwendungen auf diese Manager zugreifen.

Für die Instrumenten-Cluster-Implementierung müssen Automobil-OEMs eine benutzerdefinierte Implementierung von InstrumentClusterRendererService erstellen und die Datei config.xml “ so aktualisieren, dass sie auf diese benutzerdefinierte Implementierung verweist.

Beim Rendern eines Instrumentenclusters liest der CarService während des Startvorgangs den Schlüssel InstrumentClusterRendererService der config.xml , um eine Implementierung von InstrumentClusterService zu lokalisieren. In AOSP verweist dieser Eintrag auf den Renderdienst für die Beispiel-Clusterimplementierung der Navigationsstatus-API:

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

Der Dienst, auf den in diesem Eintrag verwiesen wird, wird initialisiert und an CarService gebunden. Wenn Navigations-Apps wie Google Maps einen CarInstrumentClusterManager anfordern, stellt CarService einen Manager bereit, der den Zustand des Kombiinstruments aus dem gebundenen InstrumentClusterRenderingService aktualisiert. (In diesem Fall bezieht sich gebunden auf Android Services .)

Kombiinstrument-Service

OEMs müssen ein Android-Paket (APK) erstellen, das eine Unterklasse von InstrumentClusterRendererService . Ein Beispiel finden Sie ClusterRenderingService .

Diese Klasse dient zwei Zwecken:

  • Bietet eine Android-Schnittstelle und das Instrument Cluster-Rendering-Gerät (Zweck dieser Seite).
  • Empfängt und rendert Navigationszustandsaktualisierungen, z. B. Turn-by-Turn-Navigationsanleitung.

Für den ersten Zweck müssen OEM-Implementierungen von InstrumentClusterRendererService die sekundäre Anzeige initialisieren, die zum Rendern von Informationen auf Bildschirmen in der Fahrzeugkabine verwendet wird, und diese Informationen an CarService , indem die Methoden InstrumentClusterRendererService.setClusterActivityOptions() und InstrumentClusterRendererService.setClusterActivityState() aufgerufen werden.

Für die zweite Funktion muss der Instrument Cluster-Dienst eine Implementierung der NavigationRenderer -Schnittstelle bereitstellen, die Aktualisierungsereignisse des Navigationsstatus empfängt, die als eventType codiert sind, und Ereignisdaten , die in einem Bündel codiert sind.

Integrationssequenz

Das folgende Diagramm veranschaulicht die Implementierung eines Navigationszustands, der Aktualisierungen rendert:

Integrationssequenz

In dieser Abbildung bedeuten Farben Folgendes:

  • Gelb. CarService und CarNavigationStatusManager werden von der Android-Plattform bereitgestellt. Weitere Informationen finden Sie unter Auto und CAR_NAVIGATION_SERVICE .
  • Cyan. Vom OEM implementierter InstrumentClusterRendererService .
  • Violett. Die von Google und Drittentwicklern implementierte Navigations-App.
  • Grün. CarAppFocusManager . Weitere Informationen finden Sie unter Verwenden der CarAppFocusManager-API unten und CarAppFocusManager .

Der Navigationsstatus-Informationsfluss folgt dieser Reihenfolge:

  1. CarService initialisiert den InstrumentClusterRenderingService .
  2. Während der Initialisierung aktualisiert der InstrumentClusterRenderingService CarService mit:
    1. Anzeigeeigenschaften des Instrumentenclusters, z. B. deutliche Grenzen (weitere Einzelheiten zu deutlichen Grenzen siehe später).
    2. Aktivitätsoptionen, die zum Starten von Aktivitäten in der Instrumenten-Cluster-Anzeige erforderlich sind (weitere Einzelheiten finden Sie unter ActivityOptions .
  3. Eine Navigations-App (z. B. Google Maps für Android Automotive oder eine beliebige Karten-App mit den erforderlichen Berechtigungen):
    1. Ruft einen CarAppFocusManager , der die Car-Klasse von car-lib verwendet.
    2. Ruft vor Beginn der Abbiegehinweise CarAppFocusManager.requestFocus() auf, um CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION als appType Parameter zu übergeben.
  4. CarAppFocusManager übermittelt diese Anfrage an CarService . Wenn gewährt, überprüft CarService das Navigations-App-Paket und findet eine Aktivität, die mit der Kategorie android.car.cluster.NAVIGATION gekennzeichnet ist.
  5. Wenn sie gefunden wird, verwendet die Navigations-App die vom InstrumentClusterRenderingService gemeldeten ActivityOptions , um die Aktivität zu starten, und fügt die Anzeigeeigenschaften des Instrumentenclusters als Extras in die Absicht ein.

Integration der API

Die InstrumentClusterRenderingService Implementierung muss:

  • Als Singleton-Dienst bezeichnet werden, indem der AndroidManifest.xml der folgende Wert hinzugefügt wird. Dies ist notwendig, um sicherzustellen, dass eine einzelne Kopie des Instrument Cluster-Dienstes ausgeführt wird, auch während der Initialisierung und des Benutzerwechsels:
    android:singleUser="true"
  • Besitzen Sie die Systemberechtigung BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE . Dadurch wird sichergestellt, dass nur der im Android-Systemabbild enthaltene Instrument Cluster Rendering Service jemals an den CarService :
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    
    gebunden ist

Implementieren von InstrumentClusterRenderingService

So erstellen Sie den Dienst:

  1. Schreiben Sie eine Klasse, die sich von InstrumentClusterRenderingService erstreckt, und fügen Sie dann einen entsprechenden Eintrag zu Ihrer AndroidManifest.xml -Datei hinzu. Diese Klasse steuert die Anzeige des Instrumentenclusters und kann ( optional ) API-Daten des Navigationszustands rendern.
  2. Verwenden Sie diesen Dienst während onCreate() , um die Kommunikation mit der Rendering-Hardware zu initialisieren. Zu den Optionen gehören:
    • Bestimmen Sie die sekundäre Anzeige, die für das Kombiinstrument verwendet werden soll.
    • Erstellen Sie eine virtuelle Anzeige, damit die Kombiinstrument-App das gerenderte Bild rendert und an eine externe Einheit überträgt (unter Verwendung eines Video-Streaming-Formats wie H.264).
  3. Wenn die oben angegebene Anzeige bereit ist, muss dieser Dienst InstrumentClusterRenderingService#setClusterActivityLaunchOptions() , um die genauen ActivityOptions zu definieren, die verwendet werden müssen, um eine Aktivität auf dem Kombiinstrument anzuzeigen. Verwenden Sie diese Parameter:
    • Kategorie. CarInstrumentClusterManager#CATEGORY_NAVIGATION
    • ActivityOptions. Eine ActivityOptions -Instanz, die verwendet werden kann, um eine Aktivität im Instrument Cluster zu starten. Zum Beispiel aus der Beispiel-Instrumentencluster-Implementierung auf AOSP:
      getService().setClusterActivityLaunchOptions(
         CATEGORY_NAVIGATION,
         ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  4. Wenn das Instrument Cluster bereit ist, Aktivitäten anzuzeigen, muss dieser Dienst InstrumentClusterRenderingService#setClusterActivityState() . Verwenden Sie diese Parameter:
    • category CarInstrumentClusterManager#CATEGORY_NAVIGATION
    • state Mit ClusterActivityState generiertes Bundle. Geben Sie unbedingt folgende Daten an:
      • visible Gibt das Kombiinstrument als sichtbar und bereit zur Anzeige von Inhalten an.
      • unobscuredBounds Ein Rechteck, das den Bereich innerhalb der Instrumentencluster-Anzeige definiert, in dem Inhalt sicher angezeigt werden kann. Zum Beispiel Bereiche, die von Skalen und Messgeräten bedeckt sind.
  5. Überschreiben Sie die Methode Service#dump() und melden Sie Statusinformationen, die für das Debugging nützlich sind (weitere Informationen finden Sie unter dumpsys ).

Beispielimplementierung von InstrumentClusterRenderingService

Das folgende Beispiel skizziert eine InstrumentClusterRenderingService -Implementierung, die ein VirtualDisplay erstellt, um den Inhalt des Instrumentenclusters auf einem physischen Remote-Display darzustellen.

Alternativ könnte dieser Code die Anzeige- displayId einer mit der HU verbundenen physikalischen sekundären Anzeige übergeben, wenn bekannt ist, dass eine verfügbar ist.

/**
* Sample {@link InstrumentClusterRenderingService} implementation
*/
public class SampleClusterServiceImpl extends InstrumentClusterRenderingService {
   // Used to retrieve or create displays
   private final DisplayManager mDisplayManager;
   // Unique identifier for the display that will 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);
  }
}

Verwenden der CarAppFocusManager-API

Die CarAppFocusManager-API stellt eine Methode namens getAppTypeOwner() , die es dem von OEMs geschriebenen Clusterdienst ermöglicht, zu wissen, welche Navigations-App zu einem bestimmten Zeitpunkt den Navigationsfokus hat. OEMs können die vorhandene CarAppFocusManager#addFocusListener() -Methode verwenden und dann getAppTypeOwner() verwenden, um zu erfahren, welche App den Fokus hat. Mit diesen Informationen können OEMs:

  • Schalten Sie die im Cluster angezeigte Aktivität auf die Cluster-Aktivität um, die von der Navigations-App bereitgestellt wird, die den Fokus hält.
  • Kann erkennen, ob die fokussierte Navigations-App eine Cluster-Aktivität aufweist oder nicht. Wenn die fokussierte Navigations-App keine Cluster-Aktivität hat (oder wenn eine solche Aktivität deaktiviert ist), können OEMs dieses Signal an das Auto-DIM senden, sodass die Navigationsfacette des Clusters insgesamt übersprungen wird.

Verwenden Sie den CarAppFocusManager , um den aktuellen Anwendungsfokus zu setzen und abzuhören, z. B. aktive Navigation oder einen Sprachbefehl. Normalerweise wird nur eine Instanz einer solchen Anwendung im System aktiv ausgeführt (oder fokussiert).

Verwenden Sie die Methode CarAppFocusManager#addFocusListener(..) , um auf Änderungen des App-Fokus zu warten:

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
}

Verwenden Sie die CarAppFocusManager#getAppTypeOwner(..) Methode, um die Paketnamen des aktuellen Eigentümers eines bestimmten Anwendungstyps abzurufen, der im Fokus steht. Diese Methode kann mehr als einen Paketnamen zurückgeben, wenn der aktuelle Eigentümer die Funktion android:sharedUserId verwendet.

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 application 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
}

...

Anhang: Verwendung der Beispielanwendung

AOSP stellt eine Beispielanwendung bereit, die die Navigationsstatus-API implementiert.

So führen Sie diese Beispielanwendung aus:

  1. Erstellen und flashen Sie Android Auto auf einer unterstützten HU. Verwenden Sie die für Ihr Gerät spezifischen Android-Anweisungen zum Erstellen und Flashen. Anweisungen finden Sie unter Verwenden von Referenztafeln .
  2. Schließen Sie ein physisches sekundäres Display an die HU an (falls unterstützt) oder schalten Sie die virtuelle sekundäre HU ein:
    1. Wählen Sie in der App „Einstellungen“ den Entwicklermodus aus.
    2. Gehen Sie zu Einstellungen > System > Erweitert > Entwickleroptionen > Zweitanzeigen simulieren .
  3. Starten Sie die HU neu. Der ClusterRenderingService -Dienst ist mit der sekundären Anzeige verbunden.
  4. So starten Sie die KitchenSink-App:
    1. Öffnen Sie die Schublade.
    2. Gehen Sie zu Inst. Cluster .
    3. Klicken Sie auf METADATEN STARTEN .

KitchenSink fordert den NAVIGATION-Fokus an, der den DirectRenderingCluster -Dienst anweist, eine simulierte Benutzeroberfläche auf dem Kombiinstrument anzuzeigen.