Detalhes técnicos

Esta seção fornece detalhes técnicos específicos do app de referência Central de controle.

A Central de controle é um app privilegiado, assinado pelo sistema e não agrupado que exige uma versão mínima do SDK 35 (Android V, nível 35 da API). O app está instalado em system/priv-app para usar System APIs. Para ler informações de mídia, o app precisa ser assinado pela plataforma. É possível atualizar o app Over-the-Air (OTA).

Serviço em segundo plano

O app Central de controle depende de um serviço em segundo plano para funcionar. O Control Center Service é iniciado no estado user-post-unlocked do ciclo de vida do usuário por Vendor ServiceController. A Central de Controle precisa estar sempre ativa e se comunicando em segundo plano. O app não pode depender de que o usuário o abra.

O Control Center Service se conecta e se comunica com outras instâncias dele mesmo em outras zonas de ocupação usando a API Communication. Ler o guia de integração é essencial para entender como as instâncias da Central de controle em cada usuário estabelecem conexões e enviam e recebem dados.

Diagrama ilustrando o serviço do Control Center sendo iniciado pelo Vendor ServiceController.
Figura 5. O serviço da Central de controle foi iniciado pelo Vendor ServiceController.

Comunicação

Depois de conectado, o Control Center Service se comunica com objetos protobuf que transmitem informações. Para transferir o protobuf para outra zona de ocupante com o Communication APIs, o protobuf é convertido em um byte array, um payload object é criado, e o Payload é enviado por 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
                 }
             }
             //…
}

Dados

As informações sobre as zonas de ocupação são armazenadas na Central de controle na forma de objetos OccupantZoneData. As mudanças no OccupantZoneData local são enviadas para outras instâncias do Control Center pelo Comms API.

Quando o Payload recebido é analisado, os dados analisados são transmitidos para o OccupantZoneStateRepository local, que, por sua vez, notifica as visualizações da mudança. A maioria dos dados é transmitida entre classes com Kotlin flows on Android.

Processar solicitações de áudio do alto-falante da cabine

Para que o motorista sempre receba pedidos de passageiros para tocar áudio nos alto-falantes da cabine, quando criado, o Control Center Service do motorista registra o Primary ZoneMedia Audio RequestCallback.

O callback é notificado sobre chamadas para CarAudioManager#requestMediaAudioOnPrimaryZone. O Control Center Service do motorista processa solicitações criando uma notificação de alerta (HUN, na sigla em inglês) que pode ser aceita ou recusada pelo CarAudioManager#allowMediaAudioOnPrimaryZone(boolean).

Assistir um vídeo em conjunto com outras telas

A opção para assistir em grupo funciona devido ao Task Mirroring APIs em CarActivityManager. O TaskMirroringManager primeiro procura o pacote do app MediaSession em execução em CarActivityManager#getVisibleTasks e depois cria um VirtualDisplay e move a tarefa visível para essa tela usando CarActivityManager#moveRootTaskToDisplay.

Isso retorna um token IBinder que o MirroredSurfaceView pode usar em um layout para mostrar a tarefa usando MirroredSurfaceView#mirrorSurface. O objeto Communication API Payload transmitiu o token para outras zonas de ocupação.

Cada instância do Control Center nessas zonas de ocupação inicia um Mirroring activity e usa esse token para preencher o MirroredSurfaceView.

Fluxo de um token de espelhamento para mostrar uma tarefa em outra tela.
Figura 6. Espelhar um fluxo de tokens.

APIs de espelhamento de tarefas

A Central de controle usa estas APIs de espelhamento de tarefas:

CarActivityManager#getVisibleTasks(int displayId)
<ActivityManager.RunningTaskInfo> chamado para a exibição do remetente.

CarActivityManager#moveRootTaskToDisplay(int virtualDisplayId)
Move a tarefa visível selecionada para uma tela virtual criada.

CarActivityManager#createTaskMirroringToken(int taskId)
Cria uma tarefa para espelhar o token IBinder e precisa ser chamada depois que a tarefa é movida para a tela virtual.

MirroredSurfaceView#mirrorSurface(IBinder token)
Um objeto de visualização personalizada que usa o token para mostrar o conteúdo da |tela virtual.

Limitações do espelhamento de tarefas na Central de controle

A Central de controle só é compatível com o espelhamento de tarefas para apps MediaSession. No entanto, a API pode espelhar qualquer tarefa. A tela virtual é criada com as dimensões da tela do remetente. Se a tela do receptor usar resoluções e dimensões diferentes, a tela virtual vai aparecer no centro da tela.

Mostrar tarefas visíveis

A Central de controle estende o chassi Theme.CarUi.NoToolbar para ser uma janela translúcida. Isso significa que, quando a Central de controle é aberta sobre uma tarefa, ela é retornada em CarActivityManager#getVisibleTasks, o que permite que a tarefa seja espelhada.

Receber informações de espelhamento

A Central de Controle notifica outros apps sobre sessões de espelhamento. Para receber atualizações, os apps precisam se vincular ao Control Center Service e enviar uma classe Handler como um cliente que recebe e processa Messages do Control Center Service.

Os apps clientes podem receber o nome do pacote do app espelhado e iniciar uma intent URI para a atividade na Central de Controle que hospeda o app espelhado com estas chaves:

  • _config_msg_mirroring_pkg_name_key_
  • _config_msg_mirroring_redirect_uri_key_

Essas configurações precisam estar nos recursos do app cliente e do Centro de controle.

Os apps clientes recebem informações de espelhamento da Central de Controle.
Figura 7. Receba informações de espelhamento da Central de Controle.

Central de controle de depuração

A classe Logger processa os registros da Central de controle, que podem ser configurados para forçar registros.

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 do sistema e capacidade de atualização

Como a Central de controle é um app do sistema e assinado pela plataforma devido ao uso de permissões somente de assinatura, ela precisa ser pré-instalada no dispositivo e só pode ser atualizada por OTA, assim como o app Car Media.

Criar o Control Center da origem

Para acessar o código-fonte da Central de controle, consulte Integrar apps não agrupados.

Privacidade do usuário com várias telas

Com a Central de controle, todos os passageiros do carro podem ver informações de mídia em todas as telas. O Google recomenda que você insira um aviso de privacidade não bloqueador para notificar os usuários. O Google recomenda fazer isso no nível do sistema, ao fazer login em uma tela.