API Instrument Cluster

Use a API Instrument Cluster (uma API do Android) para mostrar apps de navegação, incluindo o Google Maps, em uma tela secundária de um carro, como atrás do no painel de instrumentos. Nesta página, descrevemos como criar um para controlar essa tela secundária e integrar o serviço com CarService para que os apps de navegação possam mostrar uma de uma ferramenta de visualização.

Terminologia

Os termos a seguir são usados nesta página.

CarInstrumentClusterManager
Uma instância de CarManager que permite que apps externos iniciem uma atividade em o cluster de instrumentos e receba callbacks quando ele estiver pronto para ser exibido atividades.
Gerenciador de carros
Classe de base de todos os administradores usados por apps externos para interagir com recursos específicos do carro serviços implementados pelo CarService.
CarService
Serviço da Plataforma Android que fornece comunicação entre apps externos (incluindo o Google Maps) e recursos específicos para carros, como acesso ao cluster de instrumentos.
Destino
O destino final para onde o veículo navegará.
Horário previsto de chegada (HEC)
O horário previsto de chegada a um destino.
Unidade principal (HU)
Unidade computacional principal incorporada em um carro. A HU executa todo o código do Android e conectada à tela central do carro.
Cluster de instrumentos
Tela secundária localizada atrás do volante e entre o carro instrumentos. Pode ser uma unidade computacional independente conectada ao HU pela rede interna do carro (ônibus CAN) ou tela secundária anexada à HU.
InstrumentClusterRenderingService
Classe base do serviço usado para interagir com o cluster de instrumentos exibição. Os OEMs precisam fornecer uma extensão dessa classe que interaja com o hardware específico do OEM.
App KitchenSink
App de teste incluído no Android Automotive.
Rota
Um caminho específico pelo qual um veículo se desloca para chegar a um destino.
Serviço Singleton
Um serviço do Android com o atributo android:singleUser. Em no máximo uma instância do serviço é executada no sistema Android a qualquer momento.

Pré-requisitos

Antes de continuar, confira se você tem estes elementos:

  • Ambiente de desenvolvimento do Android. Para configurar o Android ambiente de desenvolvimento, consulte Requisitos de build.
  • Faça o download do código-fonte do Android. Obtenha a versão mais recente do o código-fonte do Android da ramificação pi-car-release (ou posterior), em https://android.googlesource.com
  • Unidade principal (HU). Um dispositivo Android capaz de executar Android 9 (ou versão mais recente). Este dispositivo deve ter sua própria tela e ser capaz de atualizar a tela com novos builds do Android.
  • O cluster de instrumentos é um dos seguintes:
    • Tela secundária física anexada à HU. Se o o hardware e o kernel do dispositivo oferecem suporte ao gerenciamento de várias telas.
    • Unidade independente. Qualquer unidade computacional conectada ao HU por meio de uma conexão de rede, capaz de receber e exibir um stream de vídeo na própria tela.
    • Tela emulada. Durante o desenvolvimento, você pode usar uma desses ambientes emulados:
      • Telas secundárias simuladas. Para ativar um modelo tela secundária em qualquer distribuição AOSP Android, acesse as Opções do desenvolvedor configurações no app Configurações do sistema e depois selecione Simular secundário exibições. Essa configuração é equivalente a anexar uma instância com a limitação de que essa tela é sobreposta sobre a exibição.
      • Cluster de instrumentos emulado. O Android Emulator incluído com o AAOS, é possível mostrar um cluster de instrumentos ClusterRenderingService (link em inglês).

Arquitetura de integração

Componentes de integração

Qualquer integração da API Instrument Cluster consiste nestes três componentes:

  • CarService
  • Apps de navegação
  • Serviço de cluster de instrumentos OEM

Componentes de integração

CarService

O CarService faz a mediação entre os apps de navegação e o carro, garantindo que apenas um aplicativo de navegação fica ativo a qualquer momento e somente aplicativos com a android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL permissão pode enviar dados para o carro.

O CarService inicializa todos os serviços específicos do carro e fornece acesso a esses serviços por meio de uma série de gerentes. Para interagir com os serviços, e os apps em execução no carro podem acessar esses gerenciadores.

Para a implementação de clusters de instrumentos, os OEMs automotivos precisam criar um implementação de InstrumentClusterRendererService e atualizar o ClusterRenderingService (link em inglês).

Ao renderizar um cluster de instrumentos, durante o processo de inicialização, o CarService lê a chave InstrumentClusterRendererService do ClusterRenderingService (link em inglês) para localizar uma implementação de InstrumentClusterService. No AOSP, essa entrada aponta para o serviço de renderização de implementação de cluster de exemplo da API Navigation State:

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

O serviço mencionado nesta entrada é inicializado e vinculado CarService: Quando apps de navegação, como o Google Maps, solicitam uma CarInstrumentClusterManager, CarService fornece um administrador que atualiza o estado do cluster de instrumentos do InstrumentClusterRenderingService vinculado. Nesse caso, vinculado refere-se a No Android Serviços.

Serviço de cluster de instrumentos

Os OEMs precisam criar um pacote Android (APK) que contém uma subclasse de ClusterRenderingService (link em inglês).

Essa classe serve a dois propósitos:

  • Fornece uma interface do Android e o dispositivo de renderização do cluster de instrumentos (o objetivo desta página).
  • Recebe e renderiza atualizações de estado de navegação, como a navegação guiada orientações de navegação.

Para o primeiro propósito, as implementações de OEM de InstrumentClusterRendererService. precisa inicializar a tela secundária usada para renderizar informações nas telas da cabine do carro e comunicam essas informações para CarService chamando o InstrumentClusterRendererService.setClusterActivityOptions() e InstrumentClusterRendererService.setClusterActivityState().

Para a segunda função, o serviço "Cluster de instrumentos" precisa fornecer um implementação do ClusterRenderingService (link em inglês) que recebe eventos de atualização do status da navegação, que são codificados como um eventType e dados de eventos codificados em um pacote.

Sequência de integração

O diagrama a seguir ilustra a implementação de um estado de navegação que renderiza atualizações:

Sequência de integração

Nessa ilustração, as cores indicam o seguinte:

  • Amarelo. CarService e CarNavigationStatusManager fornecidos pela plataforma Android. Para saber mais, consulte Car e CAR_NAVIGATION_SERVICE,
  • Ciano. InstrumentClusterRendererService implementado pelo OEM.
  • Roxo. O app de navegação implementado pelo Google e por terceiros desenvolvedores de aplicativos.
  • Verde. CarAppFocusManager. Para saber mais, consulte Como usar a API CarAppFocusManager abaixo e CarAppFocusManager:

O fluxo de informações do estado de navegação segue esta sequência:

  1. CarService inicializa o InstrumentClusterRenderingService.
  2. Durante a inicialização, o InstrumentClusterRenderingService é atualizado CarService por:
    1. Propriedades de exibição do cluster de instrumentos, como limites não obscuros (veja mais detalhes sobre limites não obscuros posteriormente).
    2. Opções de atividade necessárias para iniciar atividades na tela do cluster de instrumentos. Para saber mais, consulte ActivityOptions.
  3. Um app de navegação (como o Google Maps para Android Automotive ou qualquer app de mapas) com as permissões necessárias):
    1. Recebe um CarAppFocusManager usando a classe Car de car-lib.
    2. Antes do início das rotas de navegação guiada, as chamadas para CarAppFocusManager.requestFocus() para passar CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION como appType. .
  4. CarAppFocusManager comunica essa solicitação a CarService. Se concedido, CarService inspeciona o pacote do app de navegação e localiza um atividade marcada com a categoria android.car.cluster.NAVIGATION.
  5. Se encontrado, o app de navegação usa o ActivityOptions informado pelo InstrumentClusterRenderingService para iniciar a atividade e inclui o Propriedades de exibição do cluster de instrumentos como extras na intent.

Integrar a API

A implementação de InstrumentClusterRenderingService precisa:

  • Defina o serviço como um serviço Singleton adicionando o seguinte valor ao o arquivo AndroidManifest.xml. Isso é necessário para garantir que uma única cópia do arquivo O serviço do cluster de instrumentos é executado, mesmo durante a inicialização e a troca de usuários:
    android:singleUser="true"
  • Mantenha a permissão do sistema BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE. Isso garante que apenas o serviço de renderização do cluster de instrumentos da imagem do sistema Android sempre é vinculada pelo CarService:
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Implementar o InstrumentClusterRenderingService

Para criar o serviço:

  1. Escreva uma classe que se estenda da ClusterRenderingService (link em inglês) e, em seguida, adicione uma entrada correspondente ao arquivo AndroidManifest.xml. Esta turma Controla a tela do cluster de instrumentos e pode, opcionalmente, renderizar o estado de navegação. dados da API.
  2. Durante o onCreate(), use esse serviço para inicializar a comunicação com o o hardware de renderização. As opções incluem:
    • Determine a tela secundária a ser usada para o cluster de instrumentos.
    • Crie uma tela virtual para que o app do cluster de instrumentos renderize e transmita o imagem renderizada para uma unidade externa (usando um formato de streaming de vídeo, como H.264).
  3. Quando a exibição indicada acima estiver pronta, este serviço deverá chamar InstrumentClusterRenderingService#setClusterActivityLaunchOptions() para definir o ActivityOptions exato que deve ser usado para exibir uma atividade no Cluster de instrumentos. Use estes parâmetros:
    • category. ClusterRenderingService (em inglês).
    • ActivityOptions. Uma instância de ActivityOptions que pode ser usada para iniciar uma atividade no cluster de instrumentos. Por exemplo, na amostra Implementação do cluster de instrumentos no AOSP:
      getService().setClusterActivityLaunchOptions(
        CATEGORY_NAVIGATION,
        ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  4. Quando o cluster de instrumentos estiver pronto para mostrar atividades, este serviço precisará invocar InstrumentClusterRenderingService#setClusterActivityState(): Use estas parâmetros:
    • category ClusterRenderingService (em inglês).
    • state pacote gerado com ClusterRenderingService (em inglês). Lembre-se de fornecer estes dados:
      • visible: especifica o cluster de instrumentos como visível e pronto para exibir conteúdo.
      • unobscuredBounds Um retângulo que define a área dentro de Tela do cluster de instrumentos em que é seguro mostrar conteúdo. Por exemplo, áreas coberta por mostradores e medidores.
  5. Substitua o método Service#dump() e informe as informações de status úteis para: depuração (consulte dumpsys) para mais informações).

Exemplo de implementação de InstrumentClusterRenderingService

O exemplo abaixo descreve um InstrumentClusterRenderingService implementação, que cria um VirtualDisplay para apresentar o objeto Instrument Conteúdo do cluster em uma tela física remota.

Como alternativa, esse código pode transmitir o displayId de uma instância física secundária tela conectada à HU, caso haja uma disponível.

/**
* 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);
  }
}

Usar a API CarAppFocusManager

A API CarAppFocusManager fornece um método chamado getAppTypeOwner(), que permite o serviço de cluster criado por OEMs para saber qual app tem o foco de navegação em qualquer dado tempo de resposta. Os OEMs podem usar o método CarAppFocusManager#addFocusListener() atual. use getAppTypeOwner() para saber qual app está em foco. Com essas informações, Os OEMs podem:

  • Alterne a atividade mostrada no cluster para a atividade do cluster fornecida pelo app de navegação segurando o foco.
  • Pode detectar se o app de navegação em foco tem uma atividade de cluster ou não. Se o foco app de navegação não tiver uma atividade de cluster (ou, se essa atividade estiver desativada), os OEMs poderão envie esse sinal para o DIM do carro para que o atributo de navegação do cluster seja ignorado.

Use CarAppFocusManager para definir e detectar o foco atual do app, como: navegação ativa ou um comando de voz. Normalmente, apenas uma instância desse app em execução (ou em foco) no sistema.

Usar o método CarAppFocusManager#addFocusListener(..) para detectar o foco do app muda:

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
}

Use o método CarAppFocusManager#getAppTypeOwner(..) para recuperar o pacote nomes do proprietário atual de um determinado tipo de aplicativo em foco. Esse método pode retornar mais de um nome de pacote se o proprietário atual usar o recurso 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
}

...

Apêndice: usar o app de exemplo

O AOSP oferece um app de exemplo que implementa a API Navigation State.

Para executar este app de exemplo:

  1. Crie e atualize o Android Auto em uma HU compatível. Use o Instruções de criação e atualização de build do Android específicas para seu dispositivo. Para instruções, consulte Uso de placas de referência.
  2. Conecte uma tela secundária física à HU (se compatível) ou ative a HU secundária:
    1. Selecione Modo de desenvolvedor no app Configurações.
    2. Acesse Configurações > Sistema > Avançado > Opções do desenvolvedor > Simular telas secundárias.
  3. Reinicializar a HU
  4. Para iniciar o app KitchenSink:
    1. Abra a gaveta.
    2. Acesse Inst. cluster.
    3. Clique em INICIAR METADADOS.

O KitchenSink solicita o foco de NAVIGATION, que instrui o DirectRenderingCluster para exibir uma simulação de interface do usuário no cluster de instrumentos.