Dettagli tecnici

Questa sezione fornisce dettagli tecnici specifici dell'app di riferimento Control Center.

Il Centro di controllo è un'app privilegiata, firmata dal sistema e non raggruppata che richiede una versione minima dell'SDK 35 (Android V (livello API 35)). L'app è installata in system/priv-app per utilizzare System APIs. Per leggere le informazioni sui contenuti multimediali, l'app deve essere firmata dalla piattaforma. Puoi aggiornare l'app Over-the-Air (OTA).

Servizio in background

L'app Centro di controllo si basa su un servizio in background per la sua funzionalità. Control Center Service viene avviato nello stato user-post-unlocked del ciclo di vita dell'utente da Vendor ServiceController. Il Centro di controllo deve essere sempre attivo e comunicare in background. L'app non può fare affidamento sull'apertura da parte dell'utente.

Control Center Service si connette e comunica con altre proprie istanze in altre zone degli occupanti utilizzando l'API Communication. La lettura della guida all'integrazione è essenziale per comprendere in che modo le istanze del Centro di controllo di ogni utente stabiliscono le connessioni e inviano e ricevono dati.

Diagramma che illustra l'avvio del servizio Control Center da parte di Vendor ServiceController.
Figura 5. Control Center Service avviato da Vendor ServiceController.

Comunicazione

Una volta collegato, Control Center Service comunica con gli oggetti protobuf che trasmettono informazioni. Per passare il protobuf a un'altra zona occupante con il Communication APIs, il protobuf viene convertito in un byte array, viene creato un payload object e il Payload viene inviato tramite CarOccupantConnectionManager#sendPayload.

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
                 }
             }
             //…
}

Dati

Le informazioni sulle zone occupanti vengono memorizzate nel Centro di controllo sotto forma di oggetti OccupantZoneData. Le modifiche all'OccupantZoneData locale vengono inviate ad altre istanze di Control Center tramite Comms API.

Quando l'Payload ricevuto viene analizzato, i dati analizzati vengono passati all'OccupantZoneStateRepository locale, che a sua volta notifica le modifiche alle visualizzazioni. La maggior parte dei dati viene trasferita tra le classi con Kotlin flows on Android.

Gestire le richieste audio dell'altoparlante dell'abitacolo

Affinché l'autista possa sempre ricevere richieste di riproduzione audio da parte dei passeggeri tramite gli altoparlanti dell'abitacolo, al momento della creazione, il Control Center Service dell'autista registra Primary ZoneMedia Audio RequestCallback.

Il callback viene informato delle chiamate a CarAudioManager#requestMediaAudioOnPrimaryZone. Il driver Control Center Service gestisce le richieste creando una notifica in evidenza (HUN) che può essere accettata o rifiutata tramite CarAudioManager#allowMediaAudioOnPrimaryZone(boolean).

Guardare un video insieme su più schermi

La visione condivisa funziona grazie a Task Mirroring APIs in CarActivityManager. TaskMirroringManager cerca prima il pacchetto dell'app MediaSession in riproduzione in CarActivityManager#getVisibleTasks, poi crea un VirtualDisplay e sposta l'attività visibile in questo display tramite CarActivityManager#moveRootTaskToDisplay.

Viene restituito un token IBinder che MirroredSurfaceView può utilizzare in un layout per visualizzare l'attività tramite MirroredSurfaceView#mirrorSurface. L'oggetto Communication API Payload ha passato il token ad altre zone occupanti.

Ogni istanza di Control Center in queste zone occupanti avvia un Mirroring activity e utilizza questo token per compilare MirroredSurfaceView.

Flusso di un token di mirroring per visualizzare un'attività su un altro schermo.
Figura 6. Esegui il mirroring di un flusso di token.

API di mirroring delle attività

Control Center utilizza le seguenti API di mirroring delle attività:

CarActivityManager#getVisibleTasks(int displayId)
<ActivityManager.RunningTaskInfo> ha chiamato per la visualizzazione del mittente.

CarActivityManager#moveRootTaskToDisplay(int virtualDisplayId)
Sposta l'attività visibile selezionata in un display virtuale creato.

CarActivityManager#createTaskMirroringToken(int taskId)
Crea un'attività per eseguire il mirroring del token IBinder e deve essere chiamata dopo che l'attività viene spostata sul display virtuale.

MirroredSurfaceView#mirrorSurface(IBinder token)
Un oggetto di visualizzazione personalizzato che utilizza il token per visualizzare i contenuti del |display virtuale.

Limitazioni del mirroring delle attività nel Centro di controllo

Il Centro di controllo supporta il mirroring delle attività solo per le app MediaSession. Tuttavia, l'API può eseguire il mirroring di qualsiasi attività. Il display virtuale viene creato con le dimensioni del display del mittente. Se il display del ricevitore utilizza risoluzioni e dimensioni diverse, il display virtuale viene visualizzato al centro dello schermo.

Attività visibili sulla superficie

Il Centro di controllo estende il telaio Theme.CarUi.NoToolbar per creare una finestra traslucida. Ciò significa che quando il Centro di controllo viene aperto sopra un'attività, questa viene restituita in CarActivityManager#getVisibleTasks, il che consente di eseguirne il mirroring.

Ricevere informazioni sul mirroring

Il Centro di controllo invia notifiche alle altre app in merito alle sessioni di mirroring. Per ricevere aggiornamenti, le app devono essere associate a Control Center Service e inviare una classe Handler come client, che riceve e gestisce Messages da Control Center Service.

Le app client possono ricevere il nome pacchetto dell'app sottoposta a mirroring e avviare un intent URI per l'attività nel Centro di controllo che ospita l'app sottoposta a mirroring con queste chiavi:

  • _config_msg_mirroring_pkg_name_key_
  • _config_msg_mirroring_redirect_uri_key_

Queste configurazioni devono esistere nelle risorse dell'app client e in quelle del Centro di controllo.

Le app client ricevono le informazioni di mirroring dal Centro di controllo.
Figura 7. Ricevi informazioni sul mirroring dal Centro di controllo.

Centro di controllo del debug

La classe Logger gestisce i log del Centro di controllo, che possono essere configurati per forzare i log.

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)
       }
   }
...

App di sistema e aggiornabilità

Poiché il Centro di controllo è un'app di sistema e firmata dalla piattaforma a causa dell'utilizzo di autorizzazioni solo per la firma, il Centro di controllo deve essere preinstallato sul dispositivo e può essere aggiornato solo OTA, in modo simile all'app per contenuti multimediali per auto.

Creare Control Center dal codice sorgente

Per ottenere il codice sorgente del Centro di controllo, vedi Integrare app non raggruppate.

Privacy dell'utente con più display

Il Centro di controllo consente a tutti i passeggeri dell'auto di visualizzare le informazioni sui contenuti multimediali su tutti i display. Google consiglia di inserire un'informativa sulla privacy non bloccante per informare gli utenti. Google consiglia di eseguire questa operazione a livello di sistema, quando accedi a un display.