Hướng dẫn tích hợp dành cho Nhà sản xuất thiết bị gốc (OEM)

Trang này mô tả cách xử lý phương thức nhập dữ liệu xoay trong VHAL, định cấu hình bản dựng để thêm dịch vụ xoay và cách tuỳ chỉnh trải nghiệm xoay trên tất cả ứng dụng. Đối với các ứng dụng OEM được cài đặt trước, chẳng hạn như trình chạy do OEM cung cấp, hãy xem Thư viện giao diện người dùng ô tô (car-ui-library)

VHAL (Lớp trừu tượng phần cứng)

Bộ điều khiển xoay hỗ trợ các thao tác sau:

  • Dịch lên trên, xuống dưới, sang trái và sang phải.
  • Xoay theo chiều kim đồng hồ và ngược chiều kim đồng hồ.
  • Nhấn nút Căn giữa.
  • Nhấn vào nút Quay lại.
  • Nhấn nút Màn hình chính.
  • Nhấn vào các nút khác, chẳng hạn như Điện thoại và Nội dung nghe nhìn.

Hãy xem hardware/interfaces/automotive/vehicle/2.0/types.hal để biết tài liệu về các thuộc tính hệ thống và int32Values tương ứng.

VHAL phải xử lý các thao tác sau:

Hích tay

Khi người dùng đẩy bộ điều khiển xoay sang phải, VHAL sẽ sử dụng thuộc tính HW_KEY_INPUTint32Values sau đây để gửi một sự kiện đến Android:

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Hiển thị mục tiêu.

Khi người dùng thả bộ điều khiển xoay, VHAL phải sử dụng cùng một thuộc tính và mã phím bằng ACTION_UP. Nhắc nhở theo các hướng khác sẽ sử dụng mã phím tương ứng.

Không có mã phím cho đường chéo nhưng VHAL có thể kết hợp phím ngang và dọc để tạo đường chéo nếu phần cứng hỗ trợ đường chéo. Ví dụ: Nhắc nhở và ở bên trái sẽ cho ra:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN

Theo thứ tự (và sau đó), việc nhả bộ điều khiển xoay sẽ tạo ra:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

Người dùng có thể đẩy bộ điều khiển xoay theo hướng vuông góc trước khi thả ra. Ví dụ: trong các trường hợp sau:

Hướng vuông góc
Hình 1. Hướng vuông góc

Thao tác này sẽ tạo ra chuỗi sự kiện sau đây:

  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

Không tạo sự kiện lặp lại trong khi giữ bộ điều khiển xoay theo một hướng.

Xoay

Khi người dùng xoay bộ điều khiển xoay theo chiều kim đồng hồ bằng một điểm ngắt (nhấp), VHAL nên sử dụng thuộc tính HW_ROTARY_INPUT với int32Values sau để gửi một sự kiện tới Android:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Một (1) tạm giữ.
  3. Hiển thị mục tiêu.

Bạn phải đặt dấu thời gian của sự kiện thành thời gian đã trôi qua tính bằng nano giây.

Một (1) xoay ngược chiều kim đồng hồ sẽ tạo ra cùng một sự kiện nhưng có -1 cho số lượng nơi tạm giữ.

Nếu nhiều góc quay theo cùng một hướng xảy ra liên tiếp nhau, VHAL nên kết hợp các điểm chèn quảng cáo thành một sự kiện duy nhất để hệ thống không bị quá tải với các sự kiện. Trong trường hợp này, dấu thời gian của sự kiện phải là thời điểm tạm ngưng xoay đầu tiên. int32Values phải bao gồm số nano giây giữa các lần tạm ngưng liên tiếp xoay.

Ví dụ: trình tự xoay sau đây:

  • Tại thời điểm t0, người dùng đã xoay một cử chỉ chệch hướng ngược chiều kim đồng hồ.
  • Tại thời điểm t0 + 5 ns, người dùng xoay một chốt hẫng ngược chiều kim đồng hồ.
  • Tại thời điểm t0 + 8 ns, người dùng xoay một đầu hũ ngược chiều kim đồng hồ.

sẽ tạo sự kiện này:

  • Tài sản: HW_ROTARY_INPUT
  • Dấu thời gian: t0
  • int32Values:
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (ba dấu gạch chéo ngược chiều kim đồng hồ).
    3. Hiển thị mục tiêu.
    4. 5 ns giữa thời điểm tạm giữ thứ nhất và thứ hai.
    5. 3 ns giữa thời điểm tạm dừng thứ hai và thứ ba.

Nút giữa

Khi người dùng nhấn vào nút Center (Trung tâm), VHAL sẽ sử dụng HW_KEY_INPUT có thuộc tính int32Values sau để gửi một sự kiện đến Android:

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Hiển thị mục tiêu.

Khi người dùng thả bộ điều khiển xoay, VHAL phải sử dụng cùng một thuộc tính và mã phím bằng ACTION_UP.

Không tạo các sự kiện lặp lại khi nhấn và giữ nút Trung tâm.

Nút quay lại

Khi người dùng nhấn nút Quay lại, VHAL sẽ sử dụng HW_KEY_INPUT có thuộc tính int32Values sau để gửi một sự kiện đến Android:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Hiển thị mục tiêu.

Khi người dùng thả bộ điều khiển xoay, VHAL phải sử dụng cùng một thuộc tính và mã phím bằng ACTION_UP.

Không được tạo sự kiện lặp lại nào khi nhấn và giữ nút Trung tâm.

Nút trang chủ

Xử lý nút Màn hình chính giống như cách bạn sử dụng nút Quay lại nhưng dùng KEYCODE_HOME trong tổng số KEYCODE_BACK.

Các nút khác

Tuy nhiên, nếu bộ điều khiển xoay có bất kỳ nút bổ sung nào thì VHAL có thể xử lý các nút đó. OEM thích vì chúng không được xem là một phần của xoay từ góc độ của Android. Các nút này thường được xử lý như nút Quay lại và nút Màn hình chính nhưng có mã phím khác. Ví dụ: KEYCODE_CALL hoặc KEYCODE_MUSIC.

Cấu hình bản dựng

Tính năng điều hướng xoay do dịch vụ hỗ trợ tiếp cận có tên là RotaryService cung cấp. Để đưa dịch vụ này vào hình ảnh hệ thống của thiết bị, hãy thêm dòng sau vào tệp makefile:

PRODUCT_PACKAGES += CarRotaryController

Bạn cũng có thể muốn đưa các gói sau vào bản gỡ lỗi:

Dịch vụ xoay được bật tự động khi thiết bị khởi động và khi người dùng chuyển đổi xảy ra. Điều này đảm bảo rằng người dùng có thể sử dụng bộ điều khiển xoay trong quá trình thiết lập.

Nếu bạn sử dụng cùng một bản dựng cho ô tô có và không có bộ điều khiển xoay, thêm CarRotaryController như minh hoạ ở trên để bao gồm mã cần thiết trong bản dựng. Để ngăn bật dịch vụ quay trên các ô tô không quay, hãy tạo một RRO tĩnh để phủ tài nguyên chuỗi rotaryService trong packages/services/Car/service có chuỗi trống. Bạn sẽ sử dụng cùng một bản dựng, nhưng có cấu hình sản phẩm riêng biệt, dành cho thiết bị xoay và không xoay. Chỉ lựa chọn sau bao gồm lớp phủ.

Tuỳ chỉnh

OEM có thể tuỳ chỉnh logic tìm tiêu điểm, làm nổi bật tiêu điểm và một số mục bổ sung thông qua các lớp phủ tài nguyên ở các vị trí sau:

  • car-ui-library ở packages/apps/Car/libs/car-ui-lib
  • RotaryService nằm ở packages/apps/Car/RotaryController
  • Core nằm ở frameworks/base/core

Dịch nhật ký

OEM có thể định cấu hình liệu từng loại trong số hai loại nhật ký nhắc nhở có được bật hay không và nếu có, chính sách kích thước bộ nhớ đệm và chính sách hết hạn. Việc này được thực hiện bằng cách ghi đè nhiều thư viện car-ui-library của chúng tôi.

Bộ nhớ đệm nhật ký tập trung

(Android 11 QPR3, Ô tô Android 11, Android 12)
Bộ nhớ đệm trên mỗi FocusArea này lưu trữ chế độ xem tập trung gần đây nhất trong FocusArea để có thể lấy tiêu điểm khi nhắc trở lại FocusArea. Bạn có thể định cấu hình bộ nhớ đệm này bằng cách phủ các tài nguyên car-ui-library sau đây:

  • car_ui_focus_history_cache_type:
    1. Bộ nhớ đệm đã bị tắt.
    2. Bộ nhớ đệm sẽ hết hạn sau một khoảng thời gian (xem bên dưới).
    3. Bộ nhớ đệm sẽ không bao giờ hết hạn.
  • car_ui_focus_history_expiration_period_ms: Bao nhiêu mili giây trước khi bộ nhớ đệm sẽ hết hạn nếu loại bộ nhớ đệm được đặt thành hai (2) (xem ở trên).

Bộ nhớ đệm nhật ký FocusArea

(Android 11 QPR3, Ô tô Android 11, Android 12)
Bộ nhớ đệm này lưu trữ lịch sử các lời nhắc để có thể nhắc theo hướng ngược lại đưa tiêu điểm về cùng một FocusArea. Có thể định cấu hình bộ nhớ đệm này bằng cách phủ các tài nguyên car-ui-library sau đây:

  • car_ui_focus_area_history_cache_type:
    1. Bộ nhớ đệm đã bị tắt.
    2. Bộ nhớ đệm sẽ hết hạn sau một khoảng thời gian (xem bên dưới).
    3. Bộ nhớ đệm không bao giờ hết hạn.
  • car_ui_focus_area_history_expiration_period_ms: Trước bao nhiêu mili giây bộ nhớ đệm sẽ hết hạn nếu loại bộ nhớ đệm được đặt thành 2 (xem ở trên).
  • car_ui_clear_focus_area_history_when_rotating: Liệu có làm trống bộ nhớ đệm hay không khi người dùng xoay bộ điều khiển.

Góc xoay

(Android 11 QPR3, Ô tô Android 11, Android 12)
OEM có thể ghi đè 2 tài nguyên số nguyên trong RotaryService để chỉ định xem có gia tốc, chẳng hạn như tăng tốc chuột, để xoay:

  • rotation_acceleration_3x_ms: Khoảng thời gian (tính bằng mili giây) dùng để quyết định xem Google có nên tăng tốc độ xoay bộ điều khiển để tạm dừng xoay hay không. Nếu khoảng thời gian giữa thời điểm tạm ngưng này và thời gian giới hạn xoay trước đó nhỏ hơn giá trị này, nó sẽ được coi là 3 trạng thái xoay. Đặt tuỳ chọn này thành 2147483647 để vô hiệu hoá 3× tăng tốc.
  • rotation_acceleration_2x_ms: Tương tự như rotation_acceleration_3x_ms. Dùng để tăng tốc 2×. Đặt giá trị này thành 2147483647 để tắt tính năng tăng tốc 2×.

Tính năng tăng tốc hoạt động hiệu quả nhất khi có từng dấu thời gian cho mỗi trường hợp tạm ngưng xoay, dưới dạng bắt buộc thông qua VHAL. Nếu không có những thiết bị này, RotaryService giả định rằng các khoảng không quảng cáo chế độ xoay có khoảng cách đều.

/**
     * 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),

Lấy nét nổi bật

OEM có thể ghi đè lựa chọn làm nổi bật tiêu điểm mặc định trong khung Android và một số tập trung nổi bật tài nguyên trong car-ui-library.

Tiêu điểm nổi bật mặc định

Khung Android cung cấp một tiêu điểm nổi bật mặc định thông qua thuộc tính selectableItemBackground. Trong Theme.DeviceDefault, mục này tham chiếu đến item_background.xml trong Core. OEM có thể che phủ item_background.xml để thay đổi đối tượng có thể vẽ làm nổi bật tiêu điểm mặc định.

Đối tượng có thể vẽ này thường phải là StateListDrawable để điều chỉnh nền dựa trên các tổ hợp khác nhau của các tiểu bang, bao gồm android:state_focusedandroid:state_pressed. Khi người dùng sử dụng bộ điều khiển xoay để lấy tiêu điểm vào một khung hiển thị, android:state_focused sẽ là true, nhưng android:state_pressed sẽ false. Sau đó, nếu người dùng nhấn nút Căn giữa trên bộ điều khiển xoay, cả android:state_focusedandroid:state_pressed sẽ là true trong khi người dùng nhấn nút. Khi người dùng thả nút ra, chỉ còn android:state_focused true.

car-ui-library sử dụng một giao diện lấy từ Theme.DeviceDefault. Do đó, lớp phủ này ảnh hưởng đến các ứng dụng dùng thư viện này cũng như các ứng dụng dùng giao diện bất kỳ bắt nguồn từ Theme.DeviceDefault. Thao tác này sẽ không ảnh hưởng đến những ứng dụng dùng giao diện không liên quan, chẳng hạn như Theme.Material.

Tập trung làm nổi bật các tài nguyên trong car-ui-library

OEM có thể ghi đè một số tài nguyên car-ui-library để kiểm soát cách lấy nét nổi bật xem xét các khung hiển thị có điểm nổi bật ở tiêu điểm không phải hình chữ nhật (chẳng hạn như hình tròn hoặc hình viên thuốc) và ở ứng dụng dùng giao diện không bắt nguồn từ Theme.DeviceDefault. Các tài nguyên được phủ lên trên sao cho tiêu điểm đánh dấu nhất quán với đối tượng có thể vẽ làm nổi bật tiêu điểm mặc định.

(Android 11 QPR3, Ô tô Android 11, Android 12)
Sau đây là các tài nguyên dùng để cho biết khi nào một khung hiển thị được lấy làm tâm điểm nhưng không được nhấn:

  • car_ui_rotary_focus_fill_color: Màu nền.
  • car_ui_rotary_focus_stroke_color: Màu đường viền.
  • car_ui_rotary_focus_stroke_width: Độ dày của đường viền.

(Android 11 QPR3, Ô tô Android 11, Android 12)
Sau đây là các tài nguyên dùng để cho biết thời điểm một khung hiển thị được lấy làm tâm điểm nhấn:

  • car_ui_rotary_focus_pressed_fill_color: Màu nền.
  • car_ui_rotary_focus_pressed_stroke_color: Màu đường viền.
  • car_ui_rotary_focus_pressed_stroke_width: Độ dày của đường viền.

Đôi khi, một nút được chọn màu nền đồng nhất để thu hút sự chú ý của người dùng, như trong ví dụ bên dưới. Điều này có thể khiến điểm nổi bật của tiêu điểm trở nên khó nhìn.

Nút có nền đồng nhất
Hình 2. Nút có nền đồng nhất

Trong trường hợp này, nhà phát triển có thể chỉ định tính năng làm nổi bật tiêu điểm tuỳ chỉnh bằng cách sử dụng Màu secondary (phụ):
  • (Android 11 QPR3, Ô tô Android 11, 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

Bất kỳ màu nào cũng có thể trong suốt và một trong hai chiều có thể bằng 0 nếu, ví dụ: bạn chỉ muốn tô màu nền hoặc chỉ muốn vẽ đường viền.

Điểm nổi bật của FocusArea

(Android 11 QPR3, Ô tô Android 11, Android 12)
FocusArea có thể vẽ 2 loại đánh dấu khi một trong các thành phần con cháu của nó là tập trung. Bạn có thể dùng cả hai nếu muốn. Tính năng này bị tắt theo mặc định trong AOSP (Dự án nguồn mở Android) nhưng có thể được bật bằng cách ghi đè tài nguyên car-ui-library:

  • car_ui_enable_focus_area_foreground_highlight: Vẽ phần đánh dấu lên trên FocusArea và các thành phần con cháu của nó. Trong AOSP, đối tượng có thể vẽ này là một đường viền xung quanh FocusArea. OEM có thể ghi đè car_ui_focus_area_foreground_highlight đối tượng có thể vẽ.
  • car_ui_enable_focus_area_background_highlight: Vẽ phần đánh dấu lên đầu FocusArea nhưng nằm phía sau các thành phần con cháu. Trong AOSP, đối tượng có thể vẽ này là một màu nền đồng nhất. OEM có thể ghi đè đối tượng có thể vẽ car_ui_focus_area_background_highlight.

Trình chỉnh sửa phương thức nhập

Trình chỉnh sửa phương thức nhập (IME) là các phương thức nhập. Ví dụ: bàn phím ảo.

(Android 11 QPR3, Ô tô Android 11, Android 12)
OEM phải phủ tài nguyên chuỗi default_touch_input_method trong RotaryService để chỉ định ComponentName của IME dựa trên thao tác chạm. Ví dụ: nếu OEM sử dụng IME được cung cấp kèm theo Android Automotive, họ nên chỉ định com.google.android.apps.automotive.inputmethod/.InputMethodService.

(Android 11 QPR3, Ô tô Android 11, Android 12)
Nếu OEM đã tạo một IME dành riêng cho tính năng xoay, họ phải chỉ định ComponentName trong tài nguyên rotary_input_method. Nếu tài nguyên này được phủ lên, thì IME đã chỉ định sẽ được sử dụng bất cứ khi nào người dùng tương tác với đầu phát trung tâm thông qua tính năng nhắc, xoay và nút Căn giữa của bộ điều khiển xoay. Khi người dùng chạm màn hình thì IME trước đó sẽ được sử dụng. Nút Quay lại (và các nút khác trên núm xoay bộ điều khiển) không ảnh hưởng đến việc lựa chọn IME. Nếu tài nguyên này không được phủ lên, sẽ không có chuyển đổi IME xảy ra. Nút xoay không hỗ trợ chế độ xoay nên người dùng không thể nhập văn bản qua chế độ xoay bộ điều khiển nếu OEM chưa cung cấp IME xoay.

RotaryIME là một IME xoay minh hoạ. Mặc dù đây là mô hình cơ bản, nhưng cũng đủ để hãy thử chuyển đổi IME tự động được mô tả ở trên. Mã nguồn cho RotaryIME có tại packages/apps/Car/tests/RotaryIME/.

Lời nhắc ngoài màn hình

Theo mặc định, khi người dùng cố gắng di chuyển ra khỏi cạnh màn hình thì sẽ không có gì xảy ra. OEM có thể định cấu hình những gì sẽ xảy ra theo từng hướng trong số 4 hướng bằng cách chỉ định bất kỳ tổ hợp:

  1. Thao tác chung do AccessibilityService xác định. Ví dụ: GLOBAL_ACTION_BACK.
  2. Một mã phím, chẳng hạn như KEYCODE_BACK.
  3. Ý định khởi chạy một hoạt động được biểu thị dưới dạng URL.

(Android 11 QPR3, Ô tô Android 11, Android 12)
Các tài nguyên này được chỉ định bằng cách phủ các tài nguyên mảng sau đây trong RotaryService:

  • off_screen_nudge_global_actions: Mảng các thao tác chung cần thực hiện khi người dùng di chuyển lên, xuống, sang trái hoặc sang phải ra khỏi cạnh màn hình. Không có hành động chung nào được thực hiện nếu phần tử có liên quan của mảng này là -1.
  • off_screen_nudge_key_codes: Mảng mã khoá của các sự kiện nhấp chuột để chèn khi người dùng di chuyển lên, xuống, sang trái hoặc sang phải ra khỏi cạnh màn hình. Không có sự kiện nào được chèn nếu phần tử có liên quan của mảng này là 0 (KEYCODE_UNKNOWN).
  • off_screen_nudge_intents: Mảng ý định sẽ chạy một hoạt động khi người dùng di chuyển lên, xuống, sang trái hoặc sang phải ra khỏi cạnh màn hình. Không có hoạt động nào được khởi chạy nếu phần tử liên quan của mảng này trống.

Cấu hình khác

Bạn nên phủ các tài nguyên RotaryService sau:

  • (Android 11 QPR3, Ô tô Android 11, Android 12)
    config_showHeadsUpNotificationOnBottom: Giá trị Boolean để biểu thị xem thông báo quan trọng sẽ được hiển thị ở dưới cùng thay vì ở trên cùng. Thông tin này phải có cùng giá trị với config_showHeadsUpNotificationOnBottom Tài nguyên Boolean trong frameworks/base/packages/CarSystemUI/res/values/config.xml
  • (Android 11 QPR3, Ô tô Android 11, Android 12)
    notification_headsup_card_margin_horizontal: Lề trái và phải cho cửa sổ thông báo quan trọng. Tham số này phải có cùng giá trị với Tài nguyên ở notification_headsup_card_margin_horizontal packages/apps/Car/Notification/res/values/dimens.xml
  • (Android 12)
    excluded_application_overlay_window_titles: Một mảng tiêu đề của các cửa sổ không nên được coi là cửa sổ lớp phủ. Thông tin này phải bao gồm cả tiêu đề cửa sổ ứng dụng đại diện cho TaskViews hoặc TaskDisplayAreas. Theo mặc định, danh sách này chỉ chứa "Maps".

Bạn có thể phủ tài nguyên RotaryService sau đây:

  • (Android 11 QPR3, Ô tô Android 11, Android 12)
    long_press_ms: Giá trị số nguyên thể hiện số mili giây Phải giữ nút giữa để kích hoạt thao tác nhấn và giữ. Số 0 cho biết hệ thống thời gian chờ mặc định nhấn và giữ sẽ được sử dụng. Đây là giá trị mặc định.