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

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

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

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

АвтомобильИнструментКластерМенеджер
Экземпляр CarManager , который позволяет внешним приложениям запускать действие в кластере инструментов и получать обратные вызовы, когда кластер инструментов готов отображать действия.
АвтоМенеджер
Базовый класс всех менеджеров, используемых внешними приложениями для взаимодействия со службами, специфичными для автомобиля, реализованными CarService.
АвтоСервис
Служба платформы Android, которая обеспечивает связь между внешними приложениями (включая Карты Google) и специфичными для автомобиля функциями, такими как доступ к комбинации приборов.
Место назначения
Конечный пункт назначения, к которому будет двигаться транспортное средство.
Расчетное время прибытия (ETA)
Расчетное время прибытия в пункт назначения.
Головное устройство (ГУ)
Основной вычислительный блок, встроенный в автомобиль. HU запускает весь код Android и подключается к центральному дисплею автомобиля.
Комбинация приборов
Дополнительный дисплей расположен за рулем и между приборами автомобиля. Это может быть независимый вычислительный блок, подключенный к ГУ через внутреннюю сеть автомобиля (CAN-шина) или дополнительный дисплей, подключенный к ГУ.
Инструменткластеррендерингсервис
Базовый класс службы, используемой для взаимодействия с дисплеем панели приборов. 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, входящий в состав AAOS, предоставляет возможность отображать комбинацию приборов с помощью 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 .

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

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

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

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

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

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

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

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

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

  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 . Это гарантирует, что только служба рендеринга Instrument Cluster, включенная в образ системы Android, будет связана с CarService :
    <uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
    

Реализация InstrumentClusterRenderingService

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

  1. Напишите класс, наследуемый от ClusterRenderingService , а затем добавьте соответствующую запись в файл AndroidManifest.xml . Этот класс управляет отображением панели инструментов и может ( необязательно ) отображать данные API состояния навигации.
  2. Во время onCreate() используйте эту службу для инициализации связи с оборудованием рендеринга. Опции включают в себя:
    • Определите дополнительный дисплей, который будет использоваться для комбинации приборов.
    • Создайте виртуальный дисплей, чтобы приложение Instrument Cluster отображало и передавало визуализированное изображение на внешнее устройство (используя формат потокового видео, например H.264).
  3. Когда указанное выше отображение будет готово, эта служба должна вызвать InstrumentClusterRenderingService#setClusterActivityLaunchOptions() чтобы определить точные ActivityOptions , которые необходимо использовать для отображения действия в кластере инструментов. Используйте эти параметры:
    • category. Служба кластерного рендеринга .
    • ActivityOptions. Экземпляр ActivityOptions , который можно использовать для запуска действия в кластере инструментов. Например, из примера реализации кластера инструментов на AOSP:
      getService().setClusterActivityLaunchOptions(
        CATEGORY_NAVIGATION,
        ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
  4. Когда кластер инструментов готов отображать действия, эта служба должна вызвать InstrumentClusterRenderingService#setClusterActivityState() . Используйте эти параметры:
    • category ClusterRenderingService .
    • state Bundle, созданный с помощью ClusterRenderingService . Обязательно укажите данные:
      • visible Указывает комбинацию приборов как видимую и готовую к отображению содержимого.
      • unobscuredBounds Прямоугольник, определяющий область на дисплее комбинации приборов, в которой безопасно отображать контент. Например, области, покрытые циферблатами и датчиками.
  5. Переопределите метод 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. Перезагрузите ГУ.
  4. Чтобы запустить приложение KitchenSink:
    1. Откройте ящик.
    2. Перейти в Инст. Кластер .
    3. Нажмите НАЧАТЬ МЕТАДАННЫЕ .

KitchenSink запрашивает фокус НАВИГАЦИЯ, который дает указание службе DirectRenderingCluster отобразить макет пользовательского интерфейса в кластере инструментов.