Технические сведения

В этом разделе приведены технические сведения, относящиеся к справочному приложению Control Center.

Центр управления — это отдельное, привилегированное, подписанное системой приложение, для которого требуется SDK версии не ниже 35 (Android V (уровень API 35)). Для использования System APIs приложение устанавливается в system/priv-app . Для чтения информации о медиафайлах приложение должно быть подписано платформой. Вы можете обновить приложение по беспроводной связи (OTA).

Фоновая служба

Приложение Control Center использует фоновую службу для своей работы. Control Center Service запускается в состоянии user-post-unlocked в жизненном цикле пользователя с помощью Vendor ServiceController . Control Center должен быть постоянно активен и обмениваться данными в фоновом режиме — приложение не может полагаться на то, что пользователь его открывает.

Control Center Service подключается и взаимодействует с другими своими экземплярами в других зонах, используя API-интерфейс связи . Ознакомление с руководством по интеграции необходимо для понимания того, как экземпляры Control Center для каждого пользователя устанавливают соединения, отправляют и получают данные.

Диаграмма, иллюстрирующая службу центра управления, инициированную контроллером службы поставщика.
Рисунок 5. Служба центра управления, запущенная поставщиком ServiceController.

Коммуникация

После подключения Control Center Service взаимодействует с объектами protobuf , которые передают информацию. Для передачи protobuf в другую зону присутствия с помощью Communication APIs , protobuf преобразуется в byte array , создаётся payload object , который отправляется через CarOccupantConnectionManager#sendPayload Payload

message ControlCenterPayload {
    required Type messageType = 1;
    // ...
    enum Type {
       MEDIA_STATUS = 0;
       MEDIA_COMMAND = 1;
       INPUT_LOCK_COMMAND = 2;
       INPUT_LOCK_SUCCESSFUL = 3;
       CANCEL_AUDIO_REQUEST = 4;
       MIRRORING_REQUEST_RECEIVER_DECISION = 5;
       MIRRORING_SESSION_ENDED = 6;
    }
}

private fun parsePayload(
    senderZone: OccupantZoneInfo,
    payload: Payload
) {
     val parsedPayload =
         ControlCenterPayload.parseFrom(payload.bytes)
             when (parsedPayload.messageType) {
                 ControlCenterPayload.Type.MEDIA_STATUS -> {
                     // logic here
                 }
             }
             //…
}

Данные

Информация о зонах присутствия хранится в Центре управления в виде объектов OccupantZoneData . Изменения в локальных данных OccupantZoneData передаются в другие экземпляры Центра управления через Comms API .

После анализа полученной Payload проанализированные данные передаются в локальный OccupantZoneStateRepository , который, в свою очередь, уведомляет представления об изменении. Большая часть данных передается между классами с помощью Kotlin flows on Android .

Обработка запросов на аудиосигнал динамика кабины

Чтобы водитель всегда мог принимать запросы пассажиров на воспроизведение звука через динамики салона , при их создании Control Center Service водителя регистрирует Primary ZoneMedia Audio RequestCallback .

Обратный вызов уведомляется о вызовах CarAudioManager#requestMediaAudioOnPrimaryZone . Control Center Service водителя обрабатывает запросы, создавая уведомление HUN (head-up notification), которое можно принять или отклонить с помощью CarAudioManager#allowMediaAudioOnPrimaryZone(boolean) .

Совместный просмотр видео с другими экранами

Совместный просмотр работает благодаря Task Mirroring APIs в CarActivityManager . TaskMirroringManager сначала ищет пакет воспроизводимого приложения MediaSession в CarActivityManager#getVisibleTasks , а затем создаёт VirtualDisplay и перемещает видимую задачу на этот дисплей с помощью CarActivityManager#moveRootTaskToDisplay .

Это возвращает токен IBinder , который MirroredSurfaceView может использовать в макете для отображения задачи через MirroredSurfaceView#mirrorSurface . Объект Communication API Payload передал токен другим зонам присутствия.

Каждый экземпляр Центра управления в этих зонах присутствия запускает Mirroring activity и использует этот токен для заполнения MirroredSurfaceView .

Поток зеркального токена для отображения задачи на другом экране.
Рисунок 6. Зеркальное отображение потока токенов.

API зеркалирования задач

Центр управления использует следующие API зеркалирования задач:

CarActivityManager#getVisibleTasks(int displayId)
<ActivityManager.RunningTaskInfo> вызывается для отображения отправителя.

CarActivityManager#moveRootTaskToDisplay(int virtualDisplayId)
Перемещает выбранную видимую задачу на созданный виртуальный дисплей.

CarActivityManager#createTaskMirroringToken(int taskId)
Создает задачу для зеркалирования токена IBinder и должна вызываться после перемещения задачи на виртуальный дисплей.

MirroredSurfaceView#mirrorSurface(IBinder token)
Пользовательский объект представления, который использует токен для отображения содержимого виртуального дисплея.

Ограничения зеркалирования задач в Центре управления

Центр управления поддерживает зеркалирование задач только для приложений MediaSession . Однако API может зеркалировать любую задачу. Виртуальный дисплей создаётся с учётом размеров экрана отправителя. Если разрешение и размеры экрана получателя отличаются, виртуальный дисплей отображается в центре экрана.

Поверхностно видимые задачи

Центр управления расширяет тему шасси Theme.CarUi.NoToolbar , превращая её в полупрозрачное окно. Это означает, что при открытии Центра управления над задачей эта задача возвращается в CarActivityManager#getVisibleTasks , что позволяет зеркально отобразить задачу.

Получать зеркальную информацию

Центр управления уведомляет другие приложения о сеансах зеркалирования. Чтобы получать обновления, приложения должны подключиться к Control Center Service и отправить класс Handler в качестве клиента, который получает и обрабатывает Messages от Control Center Service .

Клиентские приложения могут получить имя пакета зеркалируемого приложения и запустить intent URI для действия в Центре управления, где размещено зеркалируемое приложение, с помощью следующих ключей:

  • _config_msg_mirroring_pkg_name_key_
  • _config_msg_mirroring_redirect_uri_key_

Эти конфигурации должны существовать в ресурсах клиентского приложения и в ресурсах Центра управления.

Клиентские приложения получают зеркальную информацию из Центра управления.
Рисунок 7. Получение информации о зеркалировании из Центра управления.

Центр управления отладкой

Класс Logger обрабатывает журналы Центра управления и может быть настроен для принудительного ведения журналов.

class Logger(cls: Class<*>) {

   companion object {
       private const val FORCE_LOGS = false
   }

   private val tag: String

   init {
       tag = cls.simpleName
   }

   fun v(message: String) {
       if (Log.isLoggable(tag, Log.VERBOSE) || FORCE_LOGS) {
           Log.v(tag, message)
       }
   }
...

Системное приложение и обновляемость

Поскольку Control Center является системным приложением и подписан платформой из-за использования разрешений только на подпись, Control Center должен быть предварительно установлен на устройстве и может обновляться только по воздуху, аналогично приложению Car Media .

Сборка Центра управления из исходного кода

Чтобы получить исходный код Центра управления, см. раздел Интеграция нераспакованных приложений .

Конфиденциальность пользователя с несколькими дисплеями

Центр управления позволяет всем пассажирам автомобиля просматривать медиаинформацию на всех дисплеях. Google рекомендует добавить неблокируемое уведомление о конфиденциальности для уведомления пользователей. Google рекомендует делать это на системном уровне при входе в систему на дисплее.