API del grupo de instrumentos

Utilice la API del grupo de instrumentos (una API de Android) para mostrar aplicaciones de navegación, incluido Google Maps, en una pantalla secundaria de un automóvil, como detrás del volante en el panel de instrumentos. Esta página describe cómo crear un servicio para controlar esa pantalla secundaria y luego integrar el servicio con CarService para que las aplicaciones de navegación puedan mostrar una interfaz de usuario.

Terminología

En esta página se utilizan los siguientes términos:

Término Descripción
CarInstrumentClusterManager Una instancia CarManager que permite que las aplicaciones externas inicien una actividad en el grupo de instrumentos y reciban devoluciones de llamadas cuando el grupo de instrumentos esté listo para mostrar actividades.
CarManager Clase base de todos los administradores utilizados por aplicaciones externas para interactuar con servicios específicos de automóviles implementados por CarService .
CarService Servicio de plataforma Android que proporciona comunicación entre aplicaciones externas (incluido Google Maps) y funciones específicas del automóvil, como el acceso al grupo de instrumentos.
Destino El destino final hacia el que navegará el vehículo.
ETA Hora estimada de llegada al destino.
Unidad principal (HU) Unidad computacional primaria integrada en un automóvil. El HU ejecuta todo el código de Android y está conectado a la pantalla central del automóvil.
Combinación de instrumentos Display secundario ubicado detrás del volante y entre los instrumentos del automóvil. Puede ser una unidad computacional independiente conectada al HU a través de la red interna del automóvil (bus CAN) o una pantalla secundaria conectada al HU.
InstrumentClusterRenderingService Clase base para el servicio utilizado para interactuar con la pantalla del grupo de instrumentos. Los OEM deben proporcionar una extensión de esta clase que interactúe con el hardware específico del OEM.
Aplicación KitchenSink Aplicación de prueba incluida con Android Automotive.
Ruta Camino específico por el que navega un vehículo para llegar a un destino.
servicio singleton Un servicio de Android con el atributo android:singleUser . En un momento dado, se ejecuta como máximo una instancia del servicio en el sistema Android.

Requisitos previos

Para desarrollar la integración asegúrese de contar con estos elementos:

  • Entorno de desarrollo de Android. Para configurar el entorno de desarrollo de Android, consulte Requisitos de compilación .
  • Descarga el código fuente de Android. Obtenga la última versión del código fuente de Android de la rama pi-car-release (o posterior) en https://android.googlesource.com .
  • Unidad principal (HU). Un dispositivo Android capaz de ejecutar Android 9 (o posterior). Este dispositivo debe tener su propia pantalla y ser capaz de mostrarla con nuevas versiones de Android.
  • El grupo de instrumentos es uno de los siguientes:
    • Pantalla secundaria física adjunta a la HU. Si el hardware y el kernel del dispositivo admiten la administración de múltiples pantallas.
    • Unidad independiente. Cualquier unidad computacional conectada al HU a través de una conexión de red, capaz de recibir y mostrar una secuencia de video en su propia pantalla.
    • Pantalla emulada. Durante el desarrollo, puede utilizar uno de estos entornos emulados:
      • Pantallas secundarias simuladas. Para habilitar una pantalla secundaria simulada en cualquier distribución de Android AOSP, vaya a la configuración de Opciones de desarrollador en la aplicación del sistema Configuración y luego seleccione Simular pantallas secundarias. Esta configuración equivale a conectar una pantalla secundaria física, con la limitación de que esta pantalla se superpone a la pantalla principal.
      • Cuadro de instrumentos emulado. El emulador de Android incluido con Android Automotive ofrece una opción para mostrar un grupo de instrumentos con el servicio ClusterRenderingService conectado a la pantalla secundaria.
      • emulador _qemu-pipes. El servicio ClusterRenderingService está conectado a la pantalla secundaria. Implementación de referencia del grupo de instrumentos para conectarse a esta pantalla externa emulada.

Arquitectura de integración

Componentes de integración

Cualquier integración de la API del grupo de instrumentos consta de estos tres componentes:

  • CarService
  • Aplicaciones de navegación
  • Servicio de grupo de instrumentos OEM

Componentes de integración

Servicio de auto

CarService media entre las aplicaciones de navegación y el automóvil, lo que garantiza que solo una aplicación de navegación esté activa en un momento dado y que solo las aplicaciones con el permiso android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL puedan enviar datos al automóvil.

CarService inicia todos los servicios específicos del automóvil y proporciona acceso a estos servicios a través de una serie de administradores. Para interactuar con los servicios, las aplicaciones que se ejecutan en el coche pueden acceder a estos administradores.

Para la implementación del grupo de instrumentos, los OEM automotrices deben crear una implementación personalizada de InstrumentClusterRendererService y actualizar el servicio ClusterRenderingService que está conectado a la pantalla secundaria.

Al renderizar un grupo de instrumentos, durante el proceso de arranque, CarService lee la clave InstrumentClusterRendererService del servicio ClusterRenderingService que está conectado a la pantalla secundaria. para localizar una implementación de InstrumentClusterService . En AOSP, esta entrada apunta al servicio de representación de implementación del clúster de muestra de la API de estado de navegación:

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

El servicio al que se hace referencia en esta entrada está inicializado y vinculado a CarService . Cuando las aplicaciones de navegación, como Google Maps, solicitan un CarInstrumentClusterManager , CarService proporciona un administrador que actualiza el estado del grupo de instrumentos desde el InstrumentClusterRenderingService vinculado. (En este caso, enlazado se refiere a los servicios de Android ).

Servicio del grupo de instrumentos

Los OEM deben crear un paquete de Android (APK) que contenga una subclase del servicio ClusterRenderingService conectado a la pantalla secundaria. El servicio ClusterRenderingService está conectado a la pantalla secundaria. para una muestra.

Esta clase tiene dos propósitos:

  • Proporciona una interfaz Android y el dispositivo de renderizado del grupo de instrumentos (el propósito de esta página).
  • Recibe y presenta actualizaciones del estado de navegación, como guías de navegación paso a paso.

Para el primer propósito, las implementaciones OEM de InstrumentClusterRendererService deben inicializar la pantalla secundaria utilizada para representar información en las pantallas de la cabina del automóvil y comunicar esta información a CarService llamando a los métodos InstrumentClusterRendererService.setClusterActivityOptions() e InstrumentClusterRendererService.setClusterActivityState() .

Para la segunda función, el servicio del grupo de instrumentos debe proporcionar una implementación del servicio ClusterRenderingService conectado a la pantalla secundaria. interfaz que recibe eventos de actualización del estado de navegación, que están codificados como un eventType y datos de eventos codificados en un paquete.

Secuencia de integración

El siguiente diagrama ilustra la implementación de un estado de navegación que genera actualizaciones:

Secuencia de integración

En esta ilustración, los colores indican lo siguiente:

  • Amarillo. CarService y CarNavigationStatusManager proporcionados por la plataforma Android. Para obtener más información, consulte Coche y CAR_NAVIGATION_SERVICE .
  • Cian. InstrumentClusterRendererService implementado por el OEM.
  • Púrpura. La aplicación de navegación implementada por Google y desarrolladores externos.
  • Verde. CarAppFocusManager . Para obtener más información, consulte Uso de la API CarAppFocusManager a continuación y CarAppFocusManager .

El flujo de información del estado de navegación sigue esta secuencia:

  1. CarService inicializa InstrumentClusterRenderingService .
  2. Durante la inicialización, InstrumentClusterRenderingService actualiza CarService con:
    1. El grupo de instrumentos muestra propiedades, como límites no oscuros (ver más detalles sobre límites no oscuros más adelante).
    2. Opciones de actividad necesarias para iniciar actividades dentro de la pantalla del grupo de instrumentos (consulte más detalles en ActivityOptions .
  3. Una aplicación de navegación (como Google Maps para Android Automotive o cualquier aplicación de mapas con los permisos necesarios):
    1. Obtiene un CarAppFocusManager usando la clase Car de car-lib.
    2. Antes de que comiencen las indicaciones paso a paso, se llaman a CarAppFocusManager.requestFocus() para pasar CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION como parámetro appType .
  4. CarAppFocusManager comunica esta solicitud a CarService . Si se concede, CarService inspecciona el paquete de la aplicación de navegación y localiza una actividad marcada con la categoría android.car.cluster.NAVIGATION .
  5. Si se encuentra, la aplicación de navegación utiliza las ActivityOptions informadas por InstrumentClusterRenderingService para iniciar la actividad e incluye las propiedades de visualización del grupo de instrumentos como extras en la intención.

Integrar la API

La implementación InstrumentClusterRenderingService debe:

  • Ser designado como un servicio singleton agregando el siguiente valor a AndroidManifest.xml. Esto es necesario para garantizar que se ejecute una única copia del servicio del grupo de instrumentos, incluso durante la inicialización y el cambio de usuario:
    android:singleUser="true"
  • Mantenga el permiso del sistema BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE . Esto garantiza que solo el servicio de representación del grupo de instrumentos incluido como parte de la imagen del sistema Android esté vinculado por CarService :
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Implementar InstrumentClusterRenderingService

Para construir el servicio:

  1. Escriba una clase que se extienda desde el servicio ClusterRenderingService conectado a la pantalla secundaria.
  2. y luego agregue la entrada correspondiente a su archivo AndroidManifest.xml . Esta clase controla la visualización del grupo de instrumentos y puede ( opcionalmente ) representar datos de la API del estado de navegación.
  3. Durante onCreate() , utilice este servicio para inicializar la comunicación con el hardware de renderizado. Las opciones incluyen:
    • Determine la pantalla secundaria que se utilizará para el grupo de instrumentos.
    • Cree una pantalla virtual para que la aplicación Instrument Cluster represente y transmita la imagen renderizada a una unidad externa (usando un formato de transmisión de video, como H.264).
  4. Cuando la pantalla indicada anteriormente esté lista, este servicio debe llamar a InstrumentClusterRenderingService#setClusterActivityLaunchOptions() para definir las ActivityOptions exactas que se deben usar para mostrar una actividad en el grupo de instrumentos. Utilice estos parámetros:
    • categoría. El servicio ClusterRenderingService está conectado a la pantalla secundaria.
    • ActivityOptions. Una instancia ActivityOptions que se puede utilizar para iniciar una actividad en el grupo de instrumentos. Por ejemplo, del ejemplo de implementación del grupo de instrumentos en AOSP:
      getService().setClusterActivityLaunchOptions(
         CATEGORY_NAVIGATION,
         ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  5. Cuando el grupo de instrumentos esté listo para mostrar actividades, este servicio debe invocar InstrumentClusterRenderingService#setClusterActivityState() . Utilice estos parámetros:
    • El servicio category ClusterRenderingService está conectado a la pantalla secundaria.
    • state El paquete generado con el servicio ClusterRenderingService está conectado a la pantalla secundaria.
    • Asegúrese de proporcionar los siguientes datos:
      • visible Especifica el grupo de instrumentos como visible y listo para mostrar contenido.
      • unobscuredBounds Un rectángulo que define el área dentro de la pantalla del grupo de instrumentos en la que es seguro mostrar contenido. Por ejemplo, áreas cubiertas por diales y medidores.
  6. Anule el método Service#dump() y reporte información de estado útil para la depuración (consulte dumpsys para obtener más información).

Ejemplo de implementación de InstrumentClusterRenderingService

El siguiente ejemplo describe una implementación de InstrumentClusterRenderingService , que crea una VirtualDisplay para presentar el contenido del grupo de instrumentos en una pantalla física remota.

Alternativamente, este código podría pasar el displayId de una pantalla secundaria física conectada a la HU, si se sabe que hay alguna disponible.

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

Utilice la API CarAppFocusManager

La API CarAppFocusManager proporciona un método llamado getAppTypeOwner() , que permite que el servicio de clúster escrito por los OEM sepa qué aplicación de navegación tiene el foco de navegación en un momento dado. Los OEM pueden usar el método CarAppFocusManager#addFocusListener() existente y luego usar getAppTypeOwner() para saber qué aplicación tiene el foco. Con esta información, los OEM pueden:

  • Cambie la actividad que se muestra en el clúster a la actividad del clúster proporcionada por la aplicación de navegación que mantiene el foco.
  • Puede detectar si la aplicación de navegación enfocada tiene actividad de clúster o no. Si la aplicación de navegación enfocada no tiene actividad de clúster (o si dicha actividad está deshabilitada), los OEM pueden enviar esta señal al DIM del automóvil para que la faceta de navegación del clúster se omita por completo.

Utilice CarAppFocusManager para configurar y escuchar el enfoque actual de la aplicación, como navegación activa o un comando de voz. Por lo general, solo una instancia de dicha aplicación se ejecuta activamente (o está enfocada) en el sistema.

Utilice el método CarAppFocusManager#addFocusListener(..) para escuchar los cambios de enfoque de la aplicación:

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
}

Utilice el método CarAppFocusManager#getAppTypeOwner(..) para recuperar los nombres de los paquetes del propietario actual de un tipo de aplicación determinado que está enfocado. Este método puede devolver más de un nombre de paquete si el propietario actual usa la función 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: use la aplicación de muestra

AOSP proporciona una aplicación de muestra que implementa la API de estado de navegación.

Para ejecutar esta aplicación de muestra:

  1. Compile y actualice Android Auto en un HU compatible. Utilice las instrucciones de compilación y actualización de Android específicas para su dispositivo. Para obtener instrucciones, consulte Uso de tableros de referencia .
  2. Conecte una pantalla secundaria física a la HU (si es compatible) o encienda la HU secundaria virtual:
    1. Seleccione Modo de desarrollador en la aplicación Configuración.
    2. Vaya a Configuración > Sistema > Avanzado > Opciones de desarrollador > Simular pantallas secundarias .
  3. Reinicie el HU. El servicio ClusterRenderingService está conectado a la pantalla secundaria.
  4. Para iniciar la aplicación KitchenSink:
    1. Abre el cajón.
    2. Ir al Inst. Grupo .
    3. Haga clic en INICIAR METADATOS .

KitchenSink solicita el enfoque de NAVEGACIÓN, que indica al servicio DirectRenderingCluster que muestre una interfaz de usuario simulada en el grupo de instrumentos.