API кластера инструментов

Используйте API-интерфейс Instrument Cluster (API Android) для отображения навигационных приложений, включая Карты Google, на дополнительном дисплее в автомобиле, например, за рулем на приборной панели. На этой странице описано, как создать службу для управления этим дополнительным дисплеем, а затем интегрировать эту службу с CarService , чтобы навигационные приложения могли отображать пользовательский интерфейс.

Терминология

На этой странице используются следующие термины:

Срок Описание
CarInstrumentClusterManager Экземпляр CarManager , который позволяет внешним приложениям запускать действие в кластере инструментов и получать обратные вызовы, когда кластер инструментов готов отображать действия.
CarManager Базовый класс всех менеджеров, используемых внешними приложениями для взаимодействия со службами, специфичными для автомобиля, реализованными CarService .
CarService Служба платформы Android, обеспечивающая связь между внешними приложениями (включая Карты Google) и специфичными для автомобиля функциями, такими как доступ к комбинации приборов.
Место назначения Конечный пункт назначения, к которому будет двигаться транспортное средство.
расчетное время прибытия Предполагаемое время прибытия в пункт назначения.
Головное устройство (ГУ) Основной вычислительный блок, встроенный в автомобиль. HU запускает весь код Android и подключается к центральному дисплею автомобиля.
Приборный щиток Дополнительный дисплей расположен за рулем и между приборами автомобиля. Это может быть независимый вычислительный блок, подключенный к ГУ через внутреннюю сеть автомобиля (CAN-шина) или дополнительный дисплей, подключенный к ГУ.
InstrumentClusterRenderingService Базовый класс службы, используемой для взаимодействия с дисплеем панели приборов. OEM-производители должны предоставить расширение этого класса, которое взаимодействует с OEM-оборудованием.
Приложение KitchenSink Тестовое приложение входит в состав Android Automotive.
Маршрут Конкретный путь, по которому движется транспортное средство, чтобы добраться до пункта назначения.
Синглтон-сервис Служба Android с атрибутом android:singleUser . В любой момент времени в системе Android работает не более одного экземпляра службы.

Предварительные условия

Для разработки интеграции обязательно наличие следующих элементов:

  • Среда разработки Android. Чтобы настроить среду разработки Android, см. раздел Требования к сборке .
  • Загрузите исходный код Android. Получите последнюю версию исходного кода Android из ветки pi-car-release (или более поздней версии) по адресу https://android.googlesource.com .
  • Головное устройство (ГУ). Устройство Android, работающее под управлением Android 9 (или более поздней версии). Это устройство должно иметь собственный дисплей и иметь возможность прошивать дисплей новыми сборками Android.
  • Комбинация приборов является одной из следующих:
    • Физический дополнительный дисплей, подключенный к HU. Если аппаратное обеспечение и ядро ​​устройства поддерживают управление несколькими дисплеями.
    • Независимый блок. Любой вычислительный блок, подключенный к ГУ через сетевое соединение, способный принимать и отображать видеопоток на собственном дисплее.
    • Эмулируемый дисплей. Во время разработки вы можете использовать одну из этих эмулируемых сред:
      • Имитация вторичных дисплеев. Чтобы включить имитацию дополнительного дисплея в любом дистрибутиве AOSP Android, перейдите в настройки «Параметры разработчика» в системном приложении «Настройки» и выберите «Имитировать дополнительные дисплеи». Эта конфигурация эквивалентна подключению физического вторичного дисплея с тем ограничением, что этот дисплей накладывается на основной дисплей.
      • Эмулируемая комбинация приборов. Эмулятор Android, входящий в состав Android Automotive, предоставляет возможность отображать комбинацию приборов с помощью службы ClusterRenderingService , подключенной к дополнительному дисплею.
      • эмулятор _qemu-pipes. Служба ClusterRenderingService подключена к дополнительному дисплею. эталонная реализация комбинации приборов для подключения к этому эмулируемому внешнему дисплею.

Интеграционная архитектура

Компоненты интеграции

Любая интеграция API инструментального кластера состоит из этих трех компонентов:

  • CarService
  • Навигационные приложения
  • OEM-сервис кластера приборов

Компоненты интеграции

Автосервис

CarService выступает посредником между навигационными приложениями и автомобилем, гарантируя, что в любой момент времени активно только одно навигационное приложение, и только приложения с разрешением android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL могут отправлять данные в автомобиль.

CarService загружает все сервисы, специфичные для автомобиля, и обеспечивает доступ к этим сервисам через ряд менеджеров. Для взаимодействия со службами приложения, работающие в автомобиле, могут получить доступ к этим менеджерам.

Для реализации кластера приборов производители автомобильного оборудования должны создать собственную реализацию InstrumentClusterRendererService и обновить службу ClusterRenderingService , подключенную к дополнительному дисплею.

При рендеринге кластера инструментов во время процесса загрузки CarService считывает ключ InstrumentClusterRendererService службы ClusterRenderingService , подключенной к дополнительному дисплею. чтобы найти реализацию InstrumentClusterService . В AOSP эта запись указывает на пример службы рендеринга реализации кластера API состояния навигации:

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

Служба, упомянутая в этой записи, инициализируется и привязывается к CarService . Когда навигационные приложения, такие как Google Maps, запрашивают CarInstrumentClusterManager , CarService предоставляет менеджер, который обновляет состояние Instrument Cluster из привязанного InstrumentClusterRenderingService . (В данном случае «привязка» относится к службам Android .)

Сервис кластера приборов

OEM-производители должны создать пакет Android (APK), содержащий подкласс службы ClusterRenderingService , подключенный к дополнительному дисплею. Служба ClusterRenderingService подключена к дополнительному дисплею. для образца.

Этот класс служит двум целям:

  • Предоставляет интерфейс Android и устройство рендеринга комбинации приборов (цель этой страницы).
  • Получает и отображает обновления состояния навигации, например пошаговые инструкции по навигации.

Для первой цели OEM-реализации InstrumentClusterRendererService должны инициализировать вторичный дисплей, используемый для отображения информации на экранах в салоне автомобиля, и передать эту информацию CarService путем вызова методов InstrumentClusterRendererService.setClusterActivityOptions() и InstrumentClusterRendererService.setClusterActivityState() .

Для второй функции служба кластера инструментов должна обеспечить реализацию службы ClusterRenderingService , подключенную к дополнительному дисплею. интерфейс, который получает события обновления статуса навигации, которые закодированы как eventType , и данные о событии, закодированные в пакете.

Последовательность интеграции

На следующей диаграмме показана реализация состояния навигации, отображающего обновления:

Последовательность интеграции

На этой иллюстрации цвета обозначают следующее:

  • Желтый. CarService и CarNavigationStatusManager , предоставляемые платформой Android. Дополнительные сведения см. в разделе Автомобиль и CAR_NAVIGATION_SERVICE .
  • Голубой. InstrumentClusterRendererService , реализованный OEM.
  • Фиолетовый. Приложение «Навигация», созданное Google и сторонними разработчиками.
  • Зеленый. CarAppFocusManager . Дополнительные сведения см. в разделах Использование API CarAppFocusManager ниже и CarAppFocusManager .

Информационный поток состояния навигации следует следующей последовательности:

  1. CarService инициализирует InstrumentClusterRenderingService .
  2. Во время инициализации InstrumentClusterRenderingService обновляет CarService :
    1. Свойства отображения кластера инструментов, такие как неясные границы (более подробную информацию о неясных границах см. ниже).
    2. Параметры действий, необходимые для запуска действий на дисплее комбинации приборов (более подробную информацию см. в разделе ActivityOptions .
  3. Навигационное приложение (например, Google Maps для Android Automotive или любое картографическое приложение с необходимыми разрешениями):
    1. Получает CarAppFocusManager , используя класс Car из car-lib.
    2. Прежде чем начать пошаговые инструкции, вызывается CarAppFocusManager.requestFocus() для передачи CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION в качестве параметра appType .
  4. CarAppFocusManager передает этот запрос в CarService . Если предоставлено, CarService проверяет пакет навигационного приложения и находит действие, отмеченное категорией android.car.cluster.NAVIGATION .
  5. Если оно найдено, навигационное приложение использует ActivityOptions , сообщаемые InstrumentClusterRenderingService для запуска действия и включает свойства отображения кластера инструментов в качестве дополнительных элементов в намерении.

Интегрируйте API

Реализация InstrumentClusterRenderingService должна:

  • Обозначьте его как одноэлементную службу, добавив следующее значение в AndroidManifest.xml. Это необходимо для того, чтобы гарантировать запуск единственной копии службы Instrument Cluster даже во время инициализации и переключения пользователей:
    android:singleUser="true"
  • Удерживайте системное разрешение BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE . Это гарантирует, что только служба рендеринга приборной панели, включенная в образ системы Android, будет привязана к CarService :
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Реализация InstrumentClusterRenderingService

Чтобы создать сервис:

  1. Напишите класс, который расширяет службу ClusterRenderingService , подключенную к вторичному дисплею.
  2. а затем добавьте соответствующую запись в файл AndroidManifest.xml . Этот класс управляет отображением панели инструментов и может ( необязательно ) отображать данные API состояния навигации.
  3. Во время onCreate() используйте эту службу для инициализации связи с оборудованием рендеринга. Опции включают в себя:
    • Определите дополнительный дисплей, который будет использоваться для комбинации приборов.
    • Создайте виртуальный дисплей, чтобы приложение Instrument Cluster отображало и передавало визуализированное изображение на внешнее устройство (используя формат потокового видео, например H.264).
  4. Когда указанное выше отображение будет готово, эта служба должна вызвать InstrumentClusterRenderingService#setClusterActivityLaunchOptions() , чтобы определить точные ActivityOptions , которые необходимо использовать для отображения действия в кластере инструментов. Используйте эти параметры:
    • категория. Служба ClusterRenderingService подключена к дополнительному дисплею.
    • ActivityOptions. Экземпляр ActivityOptions , который можно использовать для запуска действия в кластере инструментов. Например, из примера реализации кластера приборов на AOSP:
      getService().setClusterActivityLaunchOptions(
         CATEGORY_NAVIGATION,
         ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
      
  5. Когда кластер инструментов готов отображать действия, эта служба должна вызвать InstrumentClusterRenderingService#setClusterActivityState() . Используйте эти параметры:
    • Служба category ClusterRenderingService подключена к дополнительному дисплею.
    • Пакет state , созданный с помощью службы ClusterRenderingService , подключен к дополнительному дисплею.
    • Обязательно укажите следующие данные:
      • visible Указывает комбинацию приборов как видимую и готовую к отображению содержимого.
      • unobscuredBounds Прямоугольник, определяющий область на дисплее комбинации приборов, в которой безопасно отображать контент. Например, области, покрытые циферблатами и датчиками.
  6. Переопределите метод Service#dump() и сообщите информацию о состоянии, полезную для отладки (дополнительную информацию см. в dumpsys ).

Пример реализации InstrumentClusterRenderingService

В следующем примере описывается реализация InstrumentClusterRenderingService , которая создает VirtualDisplay для представления содержимого кластера инструментов на удаленном физическом дисплее.

В качестве альтернативы этот код может передавать displayId физического вторичного дисплея, подключенного к HU, если известно, что он доступен.

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

Используйте API CarAppFocusManager.

API CarAppFocusManager предоставляет метод getAppTypeOwner() , который позволяет службе кластеров, написанной OEM-производителями, знать, какое навигационное приложение имеет фокус навигации в любой момент времени. OEM-производители могут использовать существующий метод CarAppFocusManager#addFocusListener() , а затем использовать getAppTypeOwner() , чтобы узнать, какое приложение имеет фокус. Имея эту информацию, OEM-производители могут:

  • Переключите действие, отображаемое в кластере, на действие кластера, предоставляемое навигационным приложением, удерживающим фокус.
  • Может определить, имеет ли сфокусированное навигационное приложение активность кластера или нет. Если в целевом навигационном приложении нет активности кластера (или если такая активность отключена), OEM-производители могут отправить этот сигнал в автомобильный DIM, чтобы навигационный аспект кластера был полностью пропущен.

Используйте CarAppFocusManager чтобы устанавливать и прослушивать текущий фокус приложения, например активную навигацию или голосовую команду. Обычно в системе активно работает (или фокусируется) только один экземпляр такого приложения.

Используйте метод CarAppFocusManager#addFocusListener(..) для прослушивания изменений фокуса приложения:

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
}

Используйте метод CarAppFocusManager#getAppTypeOwner(..) для получения имен пакетов текущего владельца данного типа приложения, которое находится в фокусе. Этот метод может возвращать более одного имени пакета, если текущий владелец использует функцию 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
}

...

Приложение. Использование примера приложения

AOSP предоставляет пример приложения, реализующего API состояния навигации.

Чтобы запустить этот пример приложения:

  1. Сборка и прошивка Android Auto на поддерживаемом HU. Используйте инструкции по сборке и перепрошивке Android, специфичные для вашего устройства. Инструкции см. в разделе «Использование эталонных плат» .
  2. Подключите дополнительный физический дисплей к HU (если поддерживается) или включите виртуальный вторичный HU:
    1. Выберите режим разработчика в приложении «Настройки».
    2. Откройте «Настройки» > «Система» > «Дополнительно» > «Параметры разработчика» > «Имитировать дополнительные дисплеи» .
  3. Перезагрузите ГУ. Служба ClusterRenderingService подключена к дополнительному дисплею.
  4. Чтобы запустить приложение KitchenSink:
    1. Откройте ящик.
    2. Перейти в Инст. Кластер .
    3. Нажмите НАЧАТЬ МЕТАДАННЫЕ .

KitchenSink запрашивает фокус NAVIGATION, который дает указание службе DirectRenderingCluster отобразить макет пользовательского интерфейса в кластере инструментов.