OEM 集成指南

本页介绍了如何在 VHAL 中处理旋转输入,配置您的 build 以包含旋转服务,以及如何自定义所有应用的旋转体验。对于预安装的 OEM 应用(例如 OEM 提供的启动器),请参阅 Car UI 库 (car-ui-library)

VHAL

旋转控制器支持以下操作

  • 向上、向下、向左和向右轻推。
  • 顺时针和逆时针旋转。
  • 按下“中心”按钮。
  • 按下“返回”按钮。
  • 按下“主页”按钮。
  • 按下其他按钮,例如“电话”和“媒体”。

请参阅 hardware/interfaces/automotive/vehicle/2.0/types.hal,以获取有关系统属性和相应 int32Values 的文档。

VHAL 应处理以下操作

轻推

当用户向右推动旋转控制器时,VHAL 应使用具有以下 int32ValuesHW_KEY_INPUT 属性向 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

用户可以在垂直方向推动旋转控制器,然后再释放它。例如,以下场景

Perpendicular direction
图 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 应使用具有以下 int32ValuesHW_ROTARY_INPUT 属性向 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 应使用具有以下 int32ValuesHW_KEY_INPUT 属性向 Android 发送事件

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. 目标显示屏。

当用户释放旋转控制器时,VHAL 应使用相同的属性和键代码以及 ACTION_UP

当“中心”按钮按住不放时,请勿生成重复事件。

返回按钮

当用户按下“返回”按钮时,VHAL 应使用具有以下 int32ValuesHW_KEY_INPUT 属性向 Android 发送事件

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. 目标显示屏。

当用户释放旋转控制器时,VHAL 应使用相同的属性和键代码以及 ACTION_UP

当“中心”按钮按住不放时,不应生成重复事件。

主页按钮

处理“主页”按钮的方式应与处理“返回”按钮的方式相同,但使用 KEYCODE_HOME 而不是 KEYCODE_BACK

其他按钮

如果旋转控制器包含任何其他按钮,则 VHAL 可以随意处理这些按钮,因为从 Android 的角度来看,这些按钮不被视为旋转控制器的组成部分。这些按钮通常像“返回”和“主页”按钮一样处理,但使用不同的键代码。例如,KEYCODE_CALLKEYCODE_MUSIC

构建配置

旋转导航由名为 RotaryService 的辅助功能服务提供。要将此服务包含在您设备的系统映像中,请将以下行添加到您的 makefile

PRODUCT_PACKAGES += CarRotaryController

您可能还希望在调试 build 中包含以下软件包

  • RotaryPlayground 旋转控制器的参考应用(请参阅 RotaryPlayground)。
  • RotaryIME 演示旋转 IME(请参阅输入法编辑器)。
  • CarRotaryImeRRO RotaryIME 的叠加层。

旋转服务在设备启动时以及发生用户切换时自动启用。这可确保用户可以在设置期间使用旋转控制器。

如果您对配备和未配备旋转控制器的汽车使用相同的 build,请添加如上所示的 CarRotaryController,以便必要的代码包含在 build 中。为了防止在非旋转汽车上启用旋转服务,请创建一个静态 RRO 以使用空字符串叠加 packages/services/Car/service 中的 rotaryService 字符串资源。您将对旋转和非旋转设备使用相同的 build,但具有单独的产品配置。只有后者包含叠加层。

自定义

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 Car、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 Car、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 Car、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 中,此属性指的是 Core 中的 item_background.xml。OEM 可以覆盖 item_background.xml 以更改默认焦点突出显示可绘制对象。

此可绘制对象通常应为 StateListDrawable,它会根据状态的不同组合(包括 android:state_focusedandroid:state_pressed)调整背景。当用户使用旋转控制器聚焦视图时,android:state_focused 将为 true,但 android:state_pressed 将为 false。如果用户随后按下旋转控制器上的“中心”按钮,则当用户按住按钮时,android:state_focusedandroid: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 派生的主题的应用中的外观。应叠加这些资源,以便焦点突出显示与默认焦点突出显示可绘制对象一致。

Android 11 QPR3、Android 11 Car、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 Car、Android 12
以下资源用于指示视图已聚焦已按下时的情况

  • car_ui_rotary_focus_pressed_fill_color:填充颜色。
  • car_ui_rotary_focus_pressed_stroke_color:轮廓颜色。
  • car_ui_rotary_focus_pressed_stroke_width:轮廓粗细。

有时,按钮会被赋予纯色背景颜色以引起用户的注意,如示例所示。这可能会使焦点突出显示难以看清。

Button with solid background
图 2. 具有纯色背景的按钮

在这种情况下,开发者可以使用辅助颜色指定自定义焦点突出显示
  • Android 11 QPR3、Android 11 Car、Android 12
    car_ui_rotary_focus_fill_secondary_color
    car_ui_rotary_focus_stroke_secondary_color
  • Android 12
    car_ui_rotary_focus_pressed_fill_secondary_color
    car_ui_rotary_focus_pressed_stroke_secondary_color

任何颜色都可以是透明的,并且如果例如您只想要填充或只想要轮廓,则任一尺寸都可以为零。

FocusArea 突出显示

Android 11 QPR3、Android 11 Car、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 Car、Android 12
OEM 必须覆盖 RotaryService 中的 default_touch_input_method 字符串资源,以指定基于触摸的 IME 的 ComponentName。例如,如果 OEM 使用 Android Automotive 提供的 IME,则应指定 com.google.android.apps.automotive.inputmethod/.InputMethodService

Android 11 QPR3、Android 11 Car、Android 12
如果 OEM 专门为旋转控制器创建了 IME,则应在 rotary_input_method 资源中指定其 ComponentName。如果覆盖了此资源,则每当用户通过旋转控制器的轻推、旋转和“中心”按钮与主机交互时,都会使用指定的 IME。当用户触摸屏幕时,将使用之前的 IME。“返回”按钮(和旋转控制器上的其他按钮)对 IME 选择没有影响。Carboard 不支持旋转控制器,因此如果 OEM 未提供旋转 IME,则用户无法通过旋转控制器输入文本。

RotaryIME 是演示旋转 IME。虽然是基本的,但它足以试用上述自动 IME 切换。可以在 packages/apps/Car/tests/RotaryIME/ 中找到 RotaryIME 的源代码。

屏幕外轻推

默认情况下,当用户尝试轻推屏幕边缘时,不会发生任何情况。OEM 可以通过指定以下任意组合来配置每个方向应发生的情况

  1. AccessibilityService 定义的全局操作。例如,GLOBAL_ACTION_BACK
  2. 键代码,例如 KEYCODE_BACK
  3. 表示为网址的用于启动 Activity 的 intent。

Android 11 QPR3、Android 11 Car、Android 12
这些由覆盖 RotaryService 中的以下数组资源指定

  • off_screen_nudge_global_actions:当用户向上、向下、向左或向右轻推屏幕边缘时要执行的全局操作数组。如果此数组的相关元素为 -1,则不执行全局操作。
  • off_screen_nudge_key_codes:当用户向上、向下、向左或向右轻推屏幕边缘时要注入的点击事件的键代码数组。如果此数组的相关元素为 0 (KEYCODE_UNKNOWN),则不注入任何事件。
  • off_screen_nudge_intents:当用户向上、向下、向左或向右轻推屏幕边缘时要启动 Activity 的 intent 数组。如果此数组的相关元素为空,则不启动任何 Activity。

其他配置

您应覆盖以下 RotaryService 资源

  • Android 11 QPR3、Android 11 Car、Android 12
    config_showHeadsUpNotificationOnBottom:布尔值,表示浮动通知是否应显示在底部而不是顶部。此值必须与 frameworks/base/packages/CarSystemUI/res/values/config.xml 中的 config_showHeadsUpNotificationOnBottom 布尔资源的值相同
  • Android 11 QPR3、Android 11 Car、Android 12
    notification_headsup_card_margin_horizontal:浮动通知窗口的左右边距。此值必须与 packages/apps/Car/Notification/res/values/dimens.xml 中的 notification_headsup_card_margin_horizontal 尺寸资源的值相同
  • Android 12
    excluded_application_overlay_window_titles:不应被视为叠加窗口的窗口标题数组。这应包括表示 TaskViewsTaskDisplayAreas 的应用窗口的标题。默认情况下,此列表仅包含“地图”。

您可以覆盖以下 RotaryService 资源

  • Android 11 QPR3、Android 11 Car、Android 12
    long_press_ms:整数值,表示按住“中心”按钮多少毫秒后触发长按。零表示应使用系统默认长按超时。这是默认值。