Руководство по интеграции для OEM-производителей

На этой странице описывается, как обрабатывать поворотные входы в VHAL, настраивать сборку для включения службы поворотного управления и как настроить работу поворотного устройства во всех приложениях. Информацию о предустановленных OEM-приложениях, таких как средства запуска OEM, см. в разделе Библиотека автомобильного пользовательского интерфейса (car-ui-library) .

ВХАЛ

Поворотный контроллер поддерживает следующие действия:

  • Подталкивайте вверх, вниз, влево и вправо.
  • Вращайте по часовой стрелке и против часовой стрелки.
  • Нажмите центральную кнопку.
  • Нажмите кнопку «Назад».
  • Нажмите кнопку «Домой».
  • Нажмите другие кнопки, такие как «Телефон» и «Медиа».

См. hardware/interfaces/automotive/vehicle/2.0/types.hal для получения документации по свойствам системы и соответствующим int32Values ​​.

VHAL должен обрабатывать следующие действия:

Подтолкнуть

Когда пользователь нажимает поворотный контроллер вправо, VHAL должен использовать свойство HW_KEY_INPUT со следующими int32Values ​​для отправки события в Android:

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Целевой дисплей.

Когда пользователь отпускает поворотный контроллер, VHAL должен использовать то же свойство и код клавиши, что и ACTION_UP . Для подталкивания в других направлениях следует использовать соответствующие коды клавиш.

Кодов клавиш для диагоналей нет, но VHAL может комбинировать горизонтальное и вертикальное событие для создания диагонали, если оборудование поддерживает диагонали. Например, подталкивание вверх и влево должно привести к следующему:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN

В любом порядке (и впоследствии) отпускание поворотного контроллера должно привести к:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

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

Перпендикулярное направление
Рисунок 1. Перпендикулярное направление

Это должно сгенерировать следующую последовательность событий:

  1. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  2. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
  3. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  4. HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

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

Поворот

Когда пользователь поворачивает поворотный контроллер по часовой стрелке на один фиксатор (щелчок), VHAL должен использовать свойство HW_ROTARY_INPUT со следующими int32Values ​​для отправки события в Android:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Один (1) фиксатор.
  3. Целевой дисплей.

Временная метка события должна быть установлена ​​на прошедшее время в наносекундах.

Поворот на один (1) фиксатор против часовой стрелки должен вызвать то же событие, но с -1 для количества фиксаторов.

Если несколько фиксаций вращения в одном направлении происходят в быстрой последовательности, VHAL должен объединить фиксации в одно событие, чтобы не перегружать систему событиями. В этом случае временная метка события должна указывать на момент первой фиксации вращения. int32Values ​​должно включать количество наносекунд между последовательными остановками вращения.

Например, следующая последовательность вращений:

  • В момент времени t0 пользователь повернул один фиксатор против часовой стрелки.
  • В момент времени t0 + 5 нс пользователь повернул один фиксатор против часовой стрелки.
  • В момент времени t0 + 8 нс пользователь повернул один фиксатор против часовой стрелки.

должен сгенерировать это событие:

  • Свойство: HW_ROTARY_INPUT
  • Временная метка: t0
  • int32Values :
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (три фиксации против часовой стрелки).
    3. Целевой дисплей.
    4. 5 нс между первой и второй фиксацией.
    5. 3 нс между второй и третьей фиксацией.

Центральная кнопка

Когда пользователь нажимает центральную кнопку, VHAL должен использовать свойство HW_KEY_INPUT со следующими int32Values ​​для отправки события в Android:

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Целевой дисплей.

Когда пользователь отпускает поворотный контроллер, VHAL должен использовать то же свойство и код клавиши, что и ACTION_UP .

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

Кнопка назад

Когда пользователь нажимает кнопку «Назад», VHAL должен использовать свойство HW_KEY_INPUT со следующими int32Values ​​для отправки события в Android:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Целевой дисплей.

Когда пользователь отпускает поворотный контроллер, VHAL должен использовать то же свойство и код клавиши, что и ACTION_UP .

Пока центральная кнопка удерживается нажатой, повторяющиеся события не должны генерироваться.

Главная кнопка

Обращайтесь с кнопкой «Домой» так же, как с кнопкой «Назад», но с помощью KEYCODE_HOME вместо KEYCODE_BACK .

Другие кнопки

Если поворотный контроллер включает в себя какие-либо дополнительные кнопки, VHAL может управлять ими так, как нравится OEM-производителю, поскольку они не считаются частью поворотного контроллера с точки зрения Android. Обычно они обрабатываются так же, как кнопки «Назад» и «Домой», но с разными кодами клавиш. Например, KEYCODE_CALL или KEYCODE_MUSIC .

Конфигурация сборки

Вращающаяся навигация обеспечивается службой доступности под названием RotaryService . Чтобы включить эту службу в образ системы вашего устройства, добавьте в свой make-файл следующую строку:

PRODUCT_PACKAGES += CarRotaryController

Вы также можете включить в отладочные сборки следующие пакеты:

Служба ротации включается автоматически при загрузке устройства и при переключении пользователя. Это гарантирует, что пользователь сможет использовать поворотный контроллер во время настройки.

Если вы используете одну и ту же сборку для автомобилей с поворотным контроллером и без него, добавьте CarRotaryController как показано выше, чтобы в сборку был включен необходимый код. Чтобы предотвратить включение ротационной службы на невращающихся автомобилях, создайте статический RRO, чтобы наложить строковый ресурс rotaryService в packages/services/Car/service на пустую строку. Вы будете использовать одну и ту же сборку, но иметь разные конфигурации продукта для вращающихся и неповоротных устройств. Только последний включает наложение.

Кастомизация

OEM-производители могут настраивать логику поиска фокуса, выделение фокуса и некоторые дополнительные элементы с помощью наложений ресурсов в следующих местах:

  • car-ui-library находится в packages/apps/Car/libs/car-ui-lib
  • RotaryService находится в packages/apps/Car/RotaryController
  • Core находится в frameworks/base/core

История подталкивания

OEM-производитель может настроить, включен ли каждый из двух типов истории подталкивания, и, если да, размер кэша и политику срока действия. Все это делается путем переопределения различных ресурсов car-ui-library.

Кэш истории фокуса

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
Этот кеш для каждого FocusArea хранит последнее фокусированное представление в FocusArea , чтобы его можно было сфокусировать при возврате к FocusArea . Этот кеш можно настроить путем наложения следующих ресурсов car-ui-library:

  • car_ui_focus_history_cache_type :
    1. Кэш отключен.
    2. Срок действия кэша истечет через некоторое время (см. ниже).
    3. Кэш никогда не истечет.
  • car_ui_focus_history_expiration_period_ms : сколько миллисекунд до истечения срока действия кеша, если для типа кеша установлено значение два (2) (см. выше).

Кэш истории FocusArea

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
Этот кеш хранит историю перемещений, так что перемещение в противоположном направлении может вернуть фокус в ту же самую FocusArea . Этот кеш можно настроить путем наложения следующих ресурсов car-ui-library:

  • car_ui_focus_area_history_cache_type :
    1. Кэш отключен.
    2. Срок действия кэша истекает через некоторое время (см. ниже).
    3. Срок действия кэша никогда не истекает.
  • car_ui_focus_area_history_expiration_period_ms : сколько миллисекунд до истечения срока действия кеша, если для типа кеша установлено значение 2 (см. выше).
  • car_ui_clear_focus_area_history_when_rotating : очищать ли кэш, когда пользователь поворачивает контроллер.

Вращение

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
OEM-производитель может переопределить два целочисленных ресурса в RotaryService , чтобы указать, существует ли ускорение, например ускорение мыши, для вращения:

  • rotation_acceleration_3x_ms : интервал времени (в миллисекундах), используемый для принятия решения, должен ли Google ускорить вращение контроллера для фиксации вращения. Если интервал между этой фиксацией и предыдущей фиксацией вращения меньше этого значения, он будет рассматриваться как три фиксации вращения. Установите значение 2147483647, чтобы отключить 3-кратное ускорение.
  • rotation_acceleration_2x_ms : аналогично rotation_acceleration_3x_ms . Используется для 2-кратного ускорения. Установите значение 2147483647 , чтобы отключить ускорение в 2 раза.

Ускорение работает лучше всего, когда для каждого фиксатора вращения имеются отдельные временные метки, как того требует VHAL. Если они недоступны, RotaryService предполагает, что фиксаторы вращения расположены равномерно.

/**
     * Property to feed H/W rotary events to android
     *
     * int32Values[0] : RotaryInputType identifying which rotary knob rotated
     * int32Values[1] : number of detents (clicks), positive for clockwise,
     *                  negative for counterclockwise
     * int32Values[2] : target display defined in VehicleDisplay. Events not
     *                  tied to specific display must be sent to
     *                  VehicleDisplay#MAIN.
     * int32values[3 .. 3 + abs(number of detents) - 2]:
     *                  nanosecond deltas between pairs of consecutive detents,
     *                  if the number of detents is > 1 or < -1
     *
     * VehiclePropValue.timestamp: when the rotation occurred. If the number of
     *                             detents is > 1 or < -1, this is when the
     *                             first detent of rotation occurred.
     *
     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
     * @data_enum RotaryInputType
     * @access VehiclePropertyAccess:READ
     */
    HW_ROTARY_INPUT = (
        0x0A20
        | VehiclePropertyGroup:SYSTEM
        | VehiclePropertyType:INT32_VEC
        | VehicleArea:GLOBAL),

Выделение фокуса

OEM-производитель может переопределить выделение фокуса по умолчанию в платформе Android и несколько ресурсов выделения фокуса в car-ui-library.

Выделение фокуса по умолчанию

Платформа Android обеспечивает выделение фокуса по умолчанию с помощью атрибута selectableItemBackground . В Theme.DeviceDefault этот атрибут ссылается на item_background.xml в Core . OEM-производитель может наложить item_background.xml , чтобы изменить возможность выделения фокуса по умолчанию.

Этот объект рисования обычно должен быть StateListDrawable , который настраивает фон на основе различных комбинаций состояний, включая android:state_focused и android:state_pressed . Когда пользователь использует поворотный контроллер для фокусировки представления, android:state_focused будет иметь true , а android:state_pressedfalse . Если затем пользователь нажмет центральную кнопку на поворотном контроллере, значения android:state_focused и android:state_pressed будут true , пока пользователь удерживает кнопку нажатой. Когда пользователь отпускает кнопку, только android:state_focused останется true .

car-ui-library использует тему, полученную из Theme.DeviceDefault . В результате это наложение влияет на приложения, использующие эту библиотеку, и приложения, использующие любую тему, производную от Theme.DeviceDefault . Это не повлияет на приложения, использующие несвязанную тему, например Theme.Material .

Сосредоточьтесь на выделенных ресурсах в библиотеке car-ui-library

OEM-производитель может переопределить несколько ресурсов car-ui-library, чтобы контролировать, как выглядит выделение фокуса в представлениях с непрямоугольным выделением фокуса (например, круглым или в форме таблетки), а также в приложениях, использующих тему, не являющуюся производной от Theme.DeviceDefault . Theme.DeviceDefault . Эти ресурсы должны быть перекрыты, чтобы выделение фокуса соответствовало рисуемому выделению фокуса по умолчанию .

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
Следующие ресурсы используются для указания того, когда представление находится в фокусе, но не нажимается:

  • car_ui_rotary_focus_fill_color : цвет заливки.
  • car_ui_rotary_focus_stroke_color : Цвет контура.
  • car_ui_rotary_focus_stroke_width : Толщина контура.

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
Следующие ресурсы используются для указания того, когда представление сфокусировано и нажато:

  • car_ui_rotary_focus_pressed_fill_color : Цвет заливки.
  • car_ui_rotary_focus_pressed_stroke_color : Цвет контура.
  • car_ui_rotary_focus_pressed_stroke_width : Толщина контура.

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

Кнопка со сплошным фоном
Рисунок 2. Кнопка со сплошным фоном

В этой ситуации разработчик может указать собственное выделение фокуса, используя дополнительные цвета:
  • ( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
    car_ui_rotary_focus_fill_secondary_color
    car_ui_rotary_focus_stroke_secondary_color
  • ( Андроид 12 )
    car_ui_rotary_focus_pressed_fill_secondary_color
    car_ui_rotary_focus_pressed_stroke_secondary_color

Любой из цветов может быть прозрачным, а любой размер может быть нулевым, если, например, вам нужна только заливка или только контур.

Выделение FocusArea

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
FocusArea может рисовать два типа подсветки, когда один из ее потомков находится в фокусе. При желании оба можно использовать вместе. Эта функция по умолчанию отключена в AOSP, но ее можно включить, переопределив ресурсы car-ui-library:

  • car_ui_enable_focus_area_foreground_highlight : нарисуйте подсветку поверх FocusArea и ее потомков. В AOSP этот объект рисования представляет собой контур вокруг FocusArea . OEM-производители могут переопределить элемент car_ui_focus_area_foreground_highlight .
  • car_ui_enable_focus_area_background_highlight : нарисуйте подсветку поверх FocusArea , но позади ее потомков. В AOSP этот объект представляет собой сплошную заливку. OEM-производители могут переопределить элемент car_ui_focus_area_background_highlight .

Редакторы методов ввода

Редакторы методов ввода (IME) — это методы ввода. Например, экранная клавиатура.

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
OEM-производитель должен наложить строковый ресурс default_touch_input_method в RotaryService , чтобы указать ComponentName сенсорного IME. Например, если OEM-производитель использует IME, предоставляемый Android Automotive, ему следует указать com.google.android.apps.automotive.inputmethod/.InputMethodService .

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
Если OEM-производитель создал IME специально для роторного метода, ему следует указать его ComponentName в ресурсе rotary_input_method . Если этот ресурс перекрыт, указанный IME используется всякий раз, когда пользователь взаимодействует с головным устройством посредством перемещения, поворота и центральной кнопки поворотного контроллера. Когда пользователь касается экрана, будет использоваться предыдущий IME. Кнопка «Назад» (и другие кнопки на поворотном контроллере) не влияют на выбор IME. Если этот ресурс не перекрыт, переключение IME не происходит. Carboard не поддерживает поворотный контроллер, поэтому пользователь не может вводить текст с помощью поворотного контроллера, если OEM не предоставил поворотный IME.

RotaryIME — это демонстрационный ротационный IME. Хотя это и базовый вариант, достаточно попробовать автоматическое переключение IME, описанное выше. Исходный код RotaryIME можно найти в packages/apps/Car/tests/RotaryIME/ .

Подталкивания за кадром

По умолчанию, когда пользователь пытается отодвинуть край экрана, ничего не происходит. OEM-производитель может настроить то, что должно происходить для каждого из четырех направлений, указав любую комбинацию:

  1. Глобальное действие, определенное AccessibilityService . Например, GLOBAL_ACTION_BACK .
  2. Код ключа, например KEYCODE_BACK .
  3. Намерение запустить действие, представленное в виде URL-адреса.

( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
Они определяются путем наложения следующих ресурсов массива в RotaryService :

  • off_screen_nudge_global_actions : массив глобальных действий, которые выполняются, когда пользователь сдвигает вверх, вниз, влево или вправо от края экрана. Никакое глобальное действие не выполняется, если соответствующий элемент этого массива равен -1.
  • off_screen_nudge_key_codes : Массив кодов клавиш событий щелчка, которые вводятся, когда пользователь смещает вверх, вниз, влево или вправо от края экрана. Никакие события не вводятся, если соответствующий элемент этого массива равен 0 ( KEYCODE_UNKNOWN ).
  • off_screen_nudge_intents : массив намерений для запуска действия, когда пользователь сдвигает вверх, вниз, влево или вправо от края экрана. Никакая активность не запускается, если соответствующий элемент этого массива пуст.

Другие конфигурации

Вам следует наложить следующие ресурсы RotaryService :

  • ( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
    config_showHeadsUpNotificationOnBottom : логическое значение, указывающее, должны ли хедз-ап-уведомления отображаться внизу, а не вверху. Оно должно иметь то же значение, что и логический ресурс config_showHeadsUpNotificationOnBottom в frameworks/base/packages/CarSystemUI/res/values/config.xml
  • ( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
    notification_headsup_card_margin_horizontal : левое и правое поле для окна хедз-ап уведомлений. Оно должно иметь то же значение, что и ресурс dimen notification_headsup_card_margin_horizontal в packages/apps/Car/Notification/res/values/dimens.xml
  • ( Андроид 12 )
    excluded_application_overlay_window_titles : Массив заголовков окон, которые не следует считать наложенными окнами. Сюда должны входить заголовки окон приложений, которые представляют TaskViews или TaskDisplayAreas . По умолчанию этот список содержит только «Карты».

Вы можете наложить следующий ресурс RotaryService :

  • ( Android 11 QPR3, Android 11 для автомобилей, Android 12 )
    long_press_ms : целочисленное значение, обозначающее, сколько миллисекунд необходимо удерживать центральную кнопку, чтобы вызвать длительное нажатие. Ноль указывает на то, что следует использовать системный таймаут по умолчанию при длительном нажатии. Это значение по умолчанию.