Combinación de instrumentos

Use la API del panel de instrumentos (una API de Android) para mostrar aplicaciones de navegación, incluido Google Maps, en una pantalla secundaria en 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 Un CarManager que permite que las aplicaciones externas inicien una actividad en el grupo de instrumentos y reciban devoluciones de llamada 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 del automóvil implementados por CarService .
CarService Servicio de la plataforma Android que proporciona comunicación entre aplicaciones externas (incluido Google Maps) y funciones específicas del automóvil, como el acceso al panel de instrumentos.
Destino El destino final al que navegará el vehículo.
hora estimada de llegada Hora estimada de llegada al destino.
Unidad principal (HU) Unidad computacional primaria integrada en un automóvil. La HU ejecuta todo el código de Android y está conectada a la pantalla central del automóvil.
Combinación de instrumentos Pantalla secundaria ubicada detrás del volante y entre los instrumentos del automóvil. Puede ser una unidad computacional independiente conectada a la HU a través de la red interna del automóvil (bus CAN) o una pantalla secundaria adjunta a la 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 Una ruta específica a lo largo de la cual navega un vehículo para llegar a un destino.
Servicio único Un servicio de Android con el atributo android:singleUser . En un momento dado, como máximo se ejecuta una instancia del servicio en el sistema Android.

requisitos previos

Para desarrollar la integración, asegúrese de tener estos elementos:

  • Entorno de desarrollo 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 de Cabecera (HU). Un dispositivo Android capaz de ejecutar Android 9 (o posterior). Este dispositivo debe tener su propia pantalla y ser capaz de actualizar la pantalla 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 gestión de varias pantallas.
    • Unidad independiente. Cualquier unidad computacional conectada a la HU a través de una conexión de red, capaz de recibir y mostrar un flujo 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 es equivalente a adjuntar 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 emulador de Android _qemu-pipes . Use la implementación del grupo de instrumentos de referencia DirectRenderingCluster para conectarse a esta pantalla externa emulada.

Arquitectura de integración

Componentes de integración

Cualquier integración de Instrument Cluster API 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 todos los servicios específicos del automóvil y brinda acceso a estos servicios a través de una serie de administradores. Para interactuar con los servicios, las aplicaciones que se ejecutan en el automóvil 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 archivo config.xml para señalar esa implementación personalizada.

Al representar un grupo de instrumentos, durante el proceso de arranque, CarService lee la clave InstrumentClusterRendererService del archivo config.xml para ubicar una implementación de InstrumentClusterService . En AOSP, esta entrada apunta al servicio de procesamiento de implementación de clúster de muestra de Navigation State API:

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

El servicio al que se hace referencia en esta entrada se inicializa y vincula 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 de grupo de instrumentos

Los OEM deben crear un paquete de Android (APK) que contenga una subclase de InstrumentClusterRendererService . Consulte ClusterRenderingService para obtener una muestra.

Esta clase tiene dos propósitos:

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

Para el primer propósito, las implementaciones OEM de InstrumentClusterRendererService deben inicializar la pantalla secundaria que se usa 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 de la interfaz NavigationRenderer que recibe eventos de actualización del estado de navegación, que se codifican como 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.
  • cian. InstrumentClusterRendererService implementado por el OEM.
  • Violeta. La aplicación de navegación implementada por Google y desarrolladores externos.
  • Verde. 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. Las propiedades de visualización del grupo de instrumentos, como los límites claros (vea más detalles sobre los límites claros más adelante).
    2. Opciones de actividad necesarias para iniciar actividades dentro de la pantalla del grupo de instrumentos (ver más detalles en Opciones de actividad .
  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, llama a CarAppFocusManager.requestFocus() para pasar CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION como el 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 la encuentra, la aplicación de navegación utiliza las opciones de 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.

Integrando la API

La implementación de InstrumentClusterRenderingService debe:

  • Ser designado como un servicio singleton agregando el siguiente valor a AndroidManifest.xml. Esto es necesario para garantizar que se ejecutará una única copia del servicio del grupo de instrumentos, incluso durante la inicialización y el cambio de usuario:
    android:singleUser="true"
  • Tener 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"/>
    

Implementación de InstrumentClusterRenderingService

Para construir el servicio:

  1. Escriba una clase que se extienda desde InstrumentClusterRenderingService y luego agregue una entrada correspondiente a su archivo AndroidManifest.xml . Esta clase controla la visualización del grupo de instrumentos y puede ( opcionalmente ) representar datos de API de estado de navegación.
  2. Durante onCreate() , utilice este servicio para inicializar la comunicación con el hardware de representación. Las opciones incluyen:
    • Determine la pantalla secundaria que se usará para el grupo de instrumentos.
    • Cree una pantalla virtual para que la aplicación Instrument Cluster renderice y transmita la imagen renderizada a una unidad externa (usando un formato de transmisión de video, como H.264).
  3. Cuando la pantalla indicada arriba esté lista, este servicio debe llamar a InstrumentClusterRenderingService#setClusterActivityLaunchOptions() para definir las opciones de ActivityOptions exactas que se deben usar para mostrar una actividad en el grupo de instrumentos. Utilice estos parámetros:
    • categoría. CarInstrumentClusterManager#CATEGORY_NAVIGATION
    • ActivityOptions. Una instancia de ActivityOptions que se puede usar para iniciar una actividad en el grupo de instrumentos. Por ejemplo, de la implementación del grupo de instrumentos de muestra en AOSP:
      getService().setClusterActivityLaunchOptions(
         CATEGORY_NAVIGATION,
         ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  4. Cuando el grupo de instrumentos está listo para mostrar actividades, este servicio debe invocar InstrumentClusterRenderingService#setClusterActivityState() . Utilice estos parámetros:
    • category CarInstrumentClusterManager#CATEGORY_NAVIGATION
    • paquete de state generado con ClusterActivityState . 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.
  5. Anule el método Service#dump() y presente 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 pantalla 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 una 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 that will 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);
  }
}

Uso de 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 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 grupo a la actividad del grupo proporcionada por la aplicación de navegación que mantiene el foco.
  • Puede detectar si la aplicación de navegación enfocada tiene una actividad de clúster o no. Si la aplicación de navegación enfocada no tiene una 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.

Use CarAppFocusManager para configurar y escuchar el enfoque de la aplicación actual, como la 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.

Use el 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 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 application 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: uso de 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 una HU compatible. Use las instrucciones de compilación y flasheo 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. Selecciona Modo desarrollador en la aplicación Configuración.
    2. Vaya a Configuración > Sistema > Avanzado > Opciones de desarrollador > Simular pantallas secundarias .
  3. Reinicie la HU. El servicio ClusterRenderingService está conectado a la pantalla secundaria.
  4. Para iniciar la aplicación KitchenSink:
    1. Abre el cajón.
    2. Ir a Inst. racimo
    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.