Technische Details

Dieser Abschnitt enthält technische Details zur Referenz-App für das Steuerfeld für Smart Home.

Das Kontrollzentrum ist eine nicht gebündelte, privilegierte, systemsignierte App, für die mindestens SDK-Version 35 (Android V, API‑Level 35) erforderlich ist. Die App ist in system/priv-app installiert, um System APIs zu verwenden. Zum Lesen von Medieninformationen muss die App plattformsigniert sein. Sie können die App OTA (Over The Air) aktualisieren.

Hintergrunddienst

Die Control Center App nutzt einen Hintergrunddienst für ihre Funktionen. Control Center Service wird im user-post-unlocked-Status im Nutzerlebenszyklus von Vendor ServiceController gestartet. Das Kontrollzentrum muss immer aktiv sein und im Hintergrund kommunizieren. Die App kann nicht darauf angewiesen sein, dass sie vom Nutzer geöffnet wird.

Control Center Service stellt mithilfe der Communication API eine Verbindung zu anderen Instanzen der App in anderen Insassenbereichen her und kommuniziert mit diesen. Es ist wichtig, den Integrationsleitfaden zu lesen, um zu verstehen, wie die Control Center-Instanzen auf den Geräten der einzelnen Nutzer Verbindungen herstellen und Daten senden und empfangen.

Diagramm, das zeigt, wie der Control Center-Dienst vom Vendor ServiceController initiiert wird.
Abbildung 5. Control Center-Dienst, der von Vendor ServiceController gestartet wurde.

Kommunikation

Sobald eine Verbindung hergestellt wurde, kommuniziert das Control Center Service mit protobuf-Objekten, die Informationen vermitteln. Um die protobuf mit der Communication APIs an eine andere Belegungszone zu übergeben, wird die protobuf in eine byte array umgewandelt, eine payload object wird erstellt und die Payload wird über CarOccupantConnectionManager#sendPayload gesendet.

message ControlCenterPayload {
    required Type messageType = 1;
    // ...
    enum Type {
       MEDIA_STATUS = 0;
       MEDIA_COMMAND = 1;
       INPUT_LOCK_COMMAND = 2;
       INPUT_LOCK_SUCCESSFUL = 3;
       CANCEL_AUDIO_REQUEST = 4;
       MIRRORING_REQUEST_RECEIVER_DECISION = 5;
       MIRRORING_SESSION_ENDED = 6;
    }
}

private fun parsePayload(
    senderZone: OccupantZoneInfo,
    payload: Payload
) {
     val parsedPayload =
         ControlCenterPayload.parseFrom(payload.bytes)
             when (parsedPayload.messageType) {
                 ControlCenterPayload.Type.MEDIA_STATUS -> {
                     // logic here
                 }
             }
             //…
}

Daten

Informationen zu Bewohnerzonen werden in der Steuerzentrale in Form von OccupantZoneData-Objekten gespeichert. Änderungen an der lokalen OccupantZoneData werden über die Comms API an andere Control Center-Instanzen gesendet.

Wenn das empfangene Payload geparst wird, werden die geparsten Daten an das lokale OccupantZoneStateRepository übergeben, das wiederum die Ansichten über die Änderung benachrichtigt. Die meisten Daten werden mit Kotlin flows on Android zwischen Klassen übergeben.

Anfragen für Lautsprecherwiedergabe verarbeiten

Damit der Fahrer immer Anfragen von Fahrgästen zum Abspielen von Audioinhalten über die Lautsprecher in der Kabine empfangen kann, wird bei der Erstellung des Fahrers Control Center Service die Primary ZoneMedia Audio RequestCallback registriert.

Der Callback wird über Anrufe an CarAudioManager#requestMediaAudioOnPrimaryZone benachrichtigt. Der Fahrer-Control Center Service verarbeitet Anfragen, indem er eine Kurzmitteilung (Heads-up Notification, HUN) erstellt, die über CarAudioManager#allowMediaAudioOnPrimaryZone(boolean) angenommen oder abgelehnt werden kann.

Video auf mehreren Bildschirmen gemeinsam ansehen

Das gemeinsame Ansehen funktioniert aufgrund der Task Mirroring APIs in CarActivityManager. Die TaskMirroringManager sucht zuerst nach dem Paket der MediaSession-App in CarActivityManager#getVisibleTasks und erstellt dann ein VirtualDisplay. Die sichtbare Aufgabe wird über CarActivityManager#moveRootTaskToDisplay auf dieses Display verschoben.

Dadurch wird ein IBinder-Token zurückgegeben, das MirroredSurfaceView in einem Layout verwenden kann, um die Aufgabe über MirroredSurfaceView#mirrorSurface anzuzeigen. Das Communication API Payload-Objekt hat das Token an andere Zonen mit Personen weitergegeben.

Jede Control Center-Instanz in diesen Bewohnerzonen startet ein Mirroring activity und verwendet dieses Token, um die MirroredSurfaceView zu füllen.

Ablauf eines Spiegelungstokens zum Anzeigen einer Aufgabe auf einem anderen Bildschirm.
Abbildung 6: Token-Ablauf spiegeln

APIs für die Spiegelung von Aufgaben

Im Control Center werden diese APIs zur Spiegelung von Aufgaben verwendet:

CarActivityManager#getVisibleTasks(int displayId)
<ActivityManager.RunningTaskInfo> wurde für die Anzeige des Absenders aufgerufen.

CarActivityManager#moveRootTaskToDisplay(int virtualDisplayId)
Verschiebt die ausgewählte sichtbare Aufgabe auf ein erstelltes virtuelles Display.

CarActivityManager#createTaskMirroringToken(int taskId)
Erstellt eine Aufgabe zum Spiegeln des IBinder-Tokens und sollte aufgerufen werden, nachdem die Aufgabe auf das virtuelle Display verschoben wurde.

MirroredSurfaceView#mirrorSurface(IBinder token)
Ein benutzerdefiniertes Ansichtsobjekt, das das Token verwendet, um den Inhalt des virtuellen Displays anzuzeigen.

Einschränkungen der Aufgabenübertragung im Kontrollzentrum

Das Kontrollzentrum unterstützt die Spiegelung von Aufgaben nur für MediaSession-Apps. Die API kann jedoch jede Aufgabe spiegeln. Die virtuelle Anzeige hat die Abmessungen des Senderdisplays. Wenn auf dem Display des Empfängers unterschiedliche Auflösungen und Abmessungen verwendet werden, wird das virtuelle Display in der Mitte des Bildschirms angezeigt.

Sichtbare Aufgaben anzeigen

Das Control Center erweitert das Gehäuse Theme.CarUi.NoToolbar zu einem durchscheinenden Fenster. Wenn das Kontrollzentrum über einer Aufgabe geöffnet wird, wird die Aufgabe in CarActivityManager#getVisibleTasks zurückgegeben, sodass sie gespiegelt werden kann.

Informationen zur Spiegelung erhalten

Das Kontrollzentrum benachrichtigt andere Apps über Spiegelungssitzungen. Damit Apps Updates erhalten, müssen sie an Control Center Service gebunden sein und eine Handler-Klasse als Client senden, die Messages von Control Center Service empfängt und verarbeitet.

Client-Apps können den Paketnamen der gespiegelten App empfangen und einen intent URI für die Aktivität im Kontrollzentrum starten, in dem die gespiegelte App gehostet wird. Dazu werden die folgenden Schlüssel verwendet:

  • _config_msg_mirroring_pkg_name_key_
  • _config_msg_mirroring_redirect_uri_key_

Diese Konfigurationen müssen in den Ressourcen der Client-App und in den Ressourcen des Steuerzentrums vorhanden sein.

Client-Apps erhalten Spiegelungsinformationen vom Control Center.
Abbildung 7. Spiegelungsinformationen vom Kontrollzentrum erhalten

Debug-Kontrollzentrum

Die Klasse Logger verarbeitet Control Center-Logs, die so konfiguriert werden können, dass Logs erzwungen werden.

class Logger(cls: Class<*>) {

   companion object {
       private const val FORCE_LOGS = false
   }

   private val tag: String

   init {
       tag = cls.simpleName
   }

   fun v(message: String) {
       if (Log.isLoggable(tag, Log.VERBOSE) || FORCE_LOGS) {
           Log.v(tag, message)
       }
   }
...

System-App und Aktualisierbarkeit

Da das Kontrollzentrum eine System-App ist und aufgrund der Verwendung von Berechtigungen, die nur eine Signatur erfordern, plattformsigniert ist, muss das Kontrollzentrum auf dem Gerät vorinstalliert sein und kann nur OTA aktualisiert werden, ähnlich wie die Car Media App.

Control Center aus dem Quellcode erstellen

Den Quellcode für das Kontrollzentrum finden Sie unter Ungebündelte Apps einbinden.

Datenschutz bei mehreren Displays

Im Kontrollzentrum können alle Fahrzeuginsassen Medieninformationen auf allen Displays sehen. Google empfiehlt, eine nicht blockierende Datenschutzerklärung einzufügen, um Nutzer zu informieren. Google empfiehlt, dies auf Systemebene zu tun, wenn Sie sich auf einem Display anmelden.