Trang này mô tả cách xử lý dữ liệu đầu vào xoay trong VHAL, định cấu hình bản dựng để đưa dịch vụ xoay vào 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 sẵn, 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 trên ô tô (car-ui-library).
VHAL
Bộ điều khiển xoay hỗ trợ các thao tác sau:
- Đẩy lên, xuống, 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 Trung tâm.
- Nhấn nút Quay lại.
- Nhấn nút Màn hình chính.
- Nhấn 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 sẽ 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_INPUT
với int32Values
sau đây để gửi một sự kiện đến Android:
ACTION_DOWN
KEYCODE_SYSTEM_NAVIGATION_RIGHT
- Màn hình mục tiêu.
Khi người dùng nhả tay điều khiển xoay, VHAL sẽ sử dụng cùng một thuộc tính và mã phím với ACTION_UP
. Các thao tác đẩy theo hướng khác phải sử dụng các 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 một sự kiện ngang và dọc để tạo ra đường chéo nếu phần cứng hỗ trợ đường chéo. Ví dụ: việc đẩy lên và sang trái sẽ tạo ra:
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
Trong cả hai thứ tự (và sau đó), việc thả 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 nhả. Ví dụ: trường hợp sau:

Thao tác này sẽ tạo ra trình tự sự kiện sau:
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
Không được tạo sự kiện lặp lại khi giữ tay đ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ồ một điểm dừng (nhấp), VHAL sẽ sử dụng thuộc tính HW_ROTARY_INPUT
với int32Values
sau đây để gửi một sự kiện đến Android:
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- Một (1) điểm chặn.
- Màn hình mục tiêu.
Bạn nên đặ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) điểm dừng xoay ngược chiều kim đồng hồ sẽ tạo ra cùng một sự kiện nhưng với số điểm dừng là -1.
Nếu nhiều điểm dừng xoay theo cùng một hướng xảy ra liên tiếp nhanh chóng, thì VHAL sẽ kết hợp các điểm dừng đó thành một sự kiện duy nhất để không làm quá tải hệ thống bằng 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 xảy ra điểm dừng đầu tiên của vòng quay.
int32Values
phải bao gồm số nano giây giữa các điểm chặn liên tiếp của vòng quay.
Ví dụ: trình tự xoay sau:
- Tại thời điểm t0, người dùng xoay một điểm chặn ngược chiều kim đồng hồ.
- Tại thời điểm t0 + 5 ns, người dùng xoay một điểm chặn ngược chiều kim đồng hồ.
- Tại thời điểm t0 + 8 ns, người dùng xoay một điểm chặn ngược chiều kim đồng hồ.
sẽ tạo ra sự kiện này:
- Thuộc tính:
HW_ROTARY_INPUT
- Dấu thời gian:
t0
int32Values
:ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- -3 (3 điểm dừng ngược chiều kim đồng hồ).
- Màn hình mục tiêu.
- 5 ns giữa điểm chặn đầu tiên và điểm chặn thứ hai.
- 3 ns giữa điểm chặn thứ hai và thứ ba.
Nút giữa
Khi người dùng nhấn nút Trung tâm, VHAL sẽ sử dụng thuộc tính HW_KEY_INPUT
với int32Values
sau đây để gửi một sự kiện đến Android:
ACTION_DOWN
KEYCODE_DPAD_CENTER
- Màn hình mục tiêu.
Khi người dùng nhả tay điều khiển xoay, VHAL sẽ sử dụng cùng một thuộc tính và mã phím với ACTION_UP
.
Không tạo sự kiện lặp lại khi 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 thuộc tính HW_KEY_INPUT
với int32Values
sau đây để gửi một sự kiện đến Android:
ACTION_DOWN
KEYCODE_BACK
- Màn hình mục tiêu.
Khi người dùng nhả tay điều khiển xoay, VHAL sẽ sử dụng cùng một thuộc tính và mã phím với ACTION_UP
.
Không được tạo sự kiện lặp lại khi giữ nút Trung tâm.
Nút trang chủ
Xử lý nút Màn hình chính như bạn làm với nút Quay lại, nhưng với KEYCODE_HOME
thay vì KEYCODE_BACK
.
Các nút khác
Nếu bộ điều khiển xoay có thêm bất kỳ nút nào, VHAL có thể xử lý các nút đó theo ý muốn của OEM vì chúng không được coi là một phần của bộ điều khiển xoay theo quan điểm 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 được cung cấp bởi một dịch vụ hỗ trợ tiếp cận có tên là RotaryService
.
Để đưa dịch vụ này vào hình ảnh hệ thống cho thiết bị, hãy thêm dòng sau vào tệp makefile:
PRODUCT_PACKAGES += CarRotaryController
Bạn cũng nên đưa các gói sau vào bản gỡ lỗi:
RotaryPlayground
Ứng dụng tham khảo cho phương thức nhập dữ liệu xoay (xem RotaryPlayground).RotaryIME
IME xoay minh hoạ (xem Trình chỉnh sửa phương thức nhập).CarRotaryImeRRO
Lớp phủ choRotaryIME
.
Dịch vụ xoay được tự động bật khi thiết bị khởi động và khi người dùng chuyển đổi. Đ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 cả xe có và không có bộ điều khiển xoay, hãy thêm CarRotaryController
như minh hoạ ở trên để đưa mã cần thiết vào bản dựng. Để ngăn việc bật dịch vụ xoay trên ô tô không xoay, hãy tạo một RRO tĩnh để phủ lên tài nguyên chuỗi rotaryService
trong packages/services/Car/service
bằng một 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 cho thiết bị xoay và không xoay. Chỉ lớp phủ sau mới có lớp phủ.
Tuỳ chỉnh
Nhà sản xuất thiết bị gốc (OEM) có thể tuỳ chỉnh logic tìm tiêu điểm, điểm nổi bật của tiêu điểm và một số mục bổ sung thông qua lớp phủ tài nguyên ở các vị trí sau:
- car-ui-library nằm trong
packages/apps/Car/libs/car-ui-lib
RotaryService
nằm trongpackages/apps/Car/RotaryController
Core
nằm trongframeworks/base/core
Nhật ký nhắc
Nhà sản xuất thiết bị gốc (OEM) có thể định cấu hình xem có bật hay không mỗi loại nhật ký nhắc nhở và nếu có, kích thước bộ nhớ đệm và chính sách hết hạn. Tất cả việc này được thực hiện bằng cách ghi đè nhiều tài nguyên car-ui-library.
Bộ nhớ đệm nhật ký Focus
(Android 11 QPR3, Android 11 Car, Android 12)
Bộ nhớ đệm cho mỗi FocusArea
này lưu trữ thành phần hiển thị được lấy tiêu điểm gần đây nhất trong FocusArea
để có thể lấy tiêu điểm khi đẩy 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:
-
car_ui_focus_history_cache_type
:- Bộ nhớ đệm đã bị tắt.
- Bộ nhớ đệm sẽ hết hạn sau một khoảng thời gian (xem bên dưới).
- Bộ nhớ đệm sẽ không bao giờ hết hạn.
car_ui_focus_history_expiration_period_ms
: Số mili giây trước khi bộ nhớ đệm 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, Android 11 Car, Android 12)
Bộ nhớ đệm này lưu trữ nhật ký các lần đẩy để việc đẩy theo hướng ngược lại có thể trả về tiêu điểm cho cùng một 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:
-
car_ui_focus_area_history_cache_type
:- Bộ nhớ đệm đã bị tắt.
- Bộ nhớ đệm sẽ hết hạn sau một khoảng thời gian (xem bên dưới).
- Bộ nhớ đệm không bao giờ hết hạn.
car_ui_focus_area_history_expiration_period_ms
: Số mili giây trước khi bộ nhớ đệm 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ó huỷ bộ nhớ đệm khi người dùng xoay tay điều khiển hay không.
Góc xoay
(Android 11 QPR3, Android 11 Car, Android 12)
Nhà sản xuất thiết bị gốc (OEM) có thể ghi đè hai tài nguyên số nguyên trong RotaryService
để chỉ định xem có gia tốc (chẳng hạn như gia tốc chuột) cho thao tác xoay hay không:
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 cho một điểm dừng xoay hay không. Nếu khoảng thời gian giữa điểm chặn này và điểm chặn trước đó của vòng quay nhỏ hơn giá trị này, thì khoảng thời gian đó sẽ được coi là ba điểm chặn của vòng quay. Đặt giá trị này thành 2147483647 để tắt tính năng tăng tốc gấp 3 lần.rotation_acceleration_2x_ms
: Tương tự nhưrotation_acceleration_3x_ms
. Dùng để tăng tốc 2 lần. Đặt giá trị này thành2147483647
để tắt tính năng tăng tốc 2 lần.
Tính năng tăng tốc hoạt động hiệu quả nhất khi có dấu thời gian riêng cho từng điểm dừng của vòng quay, như VHAL yêu cầu. Nếu không có các giá trị này, RotaryService
sẽ giả định rằng các điểm dừng của vòng quay được đặt cách đều nhau.
/** * 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àm nổi bật tiêu điểm
Nhà sản xuất thiết bị gốc có thể ghi đè phần làm nổi bật tiêu điểm mặc định trong khung Android và một số tài nguyên làm nổi bật tiêu điểm trong thư viện giao diện người dùng ô tô.
Làm nổi bật tiêu điểm mặc định
Khung Android cung cấp một điểm nhấn tiêu điểm mặc định thông qua thuộc tính selectableItemBackground
. Trong Theme.DeviceDefault
, thuộc tính này tham chiếu đến item_background.xml
trong Core
. Nhà sản xuất thiết bị gốc (OEM) có thể phủ item_background.xml
để thay đổi đối tượng có thể vẽ được làm điểm nhấn tiêu điểm mặc định.
Đối tượng có thể vẽ này thường là StateListDrawable
, giúp điều chỉnh nền dựa trên nhiều tổ hợp trạng thái, bao gồm cả android:state_focused
và android:state_pressed
. Khi người dùng sử dụng bộ điều khiển xoay để lấy nét một thành phần hiển thị, android:state_focused
sẽ là true
, nhưng android:state_pressed
sẽ là false
. Sau đó, nếu người dùng nhấn vào nút Trung tâm trên bộ điều khiển xoay, cả android:state_focused
và android:state_pressed
sẽ là true
trong khi người dùng giữ nút đó.
Khi người dùng nhả nút, chỉ android:state_focused
sẽ còn lại true
.
car-ui-library sử dụng giao diện bắt nguồn từ Theme.DeviceDefault
. Do đó, lớp phủ này ảnh hưởng đến các ứng dụng sử dụng thư viện này và các ứng dụng sử dụng giao diện bất kỳ bắt nguồn từ Theme.DeviceDefault
. Điều này sẽ không ảnh hưởng đến các ứng dụng sử dụng giao diện không liên quan, chẳng hạn như Theme.Material
.
Tập trung vào các tài nguyên làm nổi bật trong thư viện car-ui
Nhà sản xuất thiết bị gốc (OEM) có thể ghi đè một số tài nguyên thư viện giao diện người dùng ô tô để kiểm soát giao diện của điểm nhấn tiêu điểm trên các thành phần hiển thị có điểm nhấn 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 nang) và trong các ứng dụng sử dụng giao diện không bắt nguồn từ Theme.DeviceDefault
. Bạn nên phủ các tài nguyên này để phần làm nổi bật tiêu điểm nhất quán với phần làm nổi bật tiêu điểm mặc định có thể vẽ.
(Android 11 QPR3, Android 11 Car, Android 12)
Các tài nguyên sau đây được dùng để cho biết thời điểm một thành phần hiển thị được lấy tiêu đ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, Android 11 Car, Android 12)
Các tài nguyên sau đây được dùng để cho biết thời điểm một thành phần hiển thị được lấy làm tâm điểm và được 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 tạo màu nền đồng nhất để thu hút sự chú ý của người dùng, như trong ví dụ minh hoạ. Điều này có thể khiến bạn khó nhìn thấy điểm nhấn tiêu điểm.

Trong trường hợp này, nhà phát triển có thể chỉ định một điểm nhấn tiêu điểm tuỳ chỉnh bằng cách sử dụng màu phụ:
- (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
Bất kỳ màu nào cũng có thể trong suốt và một trong hai kích thước có thể bằng 0 nếu bạn chỉ muốn đổ màu hoặc chỉ muốn vẽ đường viền.
Làm nổi bật FocusArea
(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea
có thể vẽ hai loại điểm nổi bật khi một trong các thành phần con cháu của nó được lấy làm tâm điểm. Bạn có thể sử dụng cả hai tính năng này cùng lúc nếu muốn. Tính năng này bị tắt theo mặc định trong AOSP, nhưng bạn có thể bật bằng cách ghi đè các tài nguyên thư viện giao diện người dùng ô tô:
car_ui_enable_focus_area_foreground_highlight
: Vẽ một điểm nổi bật trênFocusArea
và các thành phần con của nó. Trong AOSP, đối tượng có thể vẽ này là một đường viền xung quanhFocusArea
. OEM có thể ghi đè đối tượng có thể vẽcar_ui_focus_area_foreground_highlight
.car_ui_enable_focus_area_background_highlight
: Vẽ một điểm nổi bật trênFocusArea
nhưng ở phía sau các thành phần con của nó. 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, Android 11 Car, Android 12)
Nhà sản xuất thiết bị gốc (OEM) phải phủ lên tài nguyên chuỗi default_touch_input_method
trong RotaryService
để chỉ định ComponentName
của IME dựa trên cảm ứng. Ví dụ: nếu OEM sử dụng IME được cung cấp cùng với Android Automotive, thì họ phải chỉ định com.google.android.apps.automotive.inputmethod/.InputMethodService
.
(Android 11 QPR3, Android 11 Car, Android 12)
Nếu nhà sản xuất thiết bị gốc (OEM) đã tạo một IME dành riêng cho bàn phím xoay, thì 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, IME được 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 nút đẩy, xoay và Trung tâm của bộ điều khiển xoay. Khi người dùng chạm vào màn hình, IME trước đó sẽ được sử dụng. Nút Quay lại (và các nút khác trên bộ điều khiển xoay) không ảnh hưởng đến lựa chọn IME. Nếu tài nguyên này không được phủ lên, thì sẽ không có hoạt động chuyển đổi IME nào xảy ra. Carboard không hỗ trợ tính năng xoay nên người dùng không thể nhập văn bản thông qua bộ điều khiển xoay nếu nhà sản xuất thiết bị gốc (OEM) chưa cung cấp IME xoay.
RotaryIME
là một IME xoay minh hoạ. Mặc dù cơ bản, nhưng bạn chỉ cần thử tính năng tự động chuyển đổi IME như mô tả ở trên là đủ. Bạn có thể tìm thấy mã nguồn cho RotaryIME
trong packages/apps/Car/tests/RotaryIME/
.
Đẩy ra khỏi màn hình
Theo mặc định, khi người dùng cố gắng đẩy ra khỏi cạnh màn hình, sẽ không có gì xảy ra. Nhà sản xuất thiết bị gốc (OEM) có thể định cấu hình những gì sẽ xảy ra cho mỗi hướng trong số 4 hướng bằng cách chỉ định bất kỳ tổ hợp nào của:
- Một thao tác chung do
AccessibilityService
xác định. Ví dụ:GLOBAL_ACTION_BACK
. - Mã khoá, chẳng hạn như
KEYCODE_BACK
. - Ý định chạy một hoạt động được biểu thị dưới dạng URL.
(Android 11 QPR3, Android 11 Car, Android 12)
Các giá trị này được chỉ định bằng cách phủ các tài nguyên mảng sau 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 đẩy lên, xuống, sang trái hoặc sang phải 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ử liên quan của mảng này là -1.off_screen_nudge_key_codes
: Mảng các mã phím của sự kiện nhấp để chèn khi người dùng đẩy lên, xuống, sang trái hoặc sang phải khỏi cạnh màn hình. Không có sự kiện nào được chèn nếu phần tử liên quan của mảng này là 0 (KEYCODE_UNKNOWN
).off_screen_nudge_intents
: Mảng ý định để khởi chạy một hoạt động khi người dùng đẩy lên, xuống, sang trái hoặc sang phải 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, Android 11 Car, Android 12)
config_showHeadsUpNotificationOnBottom
: Giá trị boolean để biểu thị việc thông báo quan trọng có nên hiển thị ở dưới cùng thay vì ở trên cùng hay không. Giá trị này phải giống với tài nguyên Booleanconfig_showHeadsUpNotificationOnBottom
trongframeworks/base/packages/CarSystemUI/res/values/config.xml
- (Android 11 QPR3, Android 11 Car, Android 12)
notification_headsup_card_margin_horizontal
: Lề trái và phải cho cửa sổ thông báo quan trọng. Giá trị này phải giống với tài nguyên kích thướcnotification_headsup_card_margin_horizontal
trongpackages/apps/Car/Notification/res/values/dimens.xml
- (Android 12)
excluded_application_overlay_window_titles
: Một mảng tên cửa sổ không được coi là cửa sổ lớp phủ. Tiêu đề này phải bao gồm tiêu đề của cửa sổ ứng dụng đại diện choTaskViews
hoặcTaskDisplayAreas
. Theo mặc định, danh sách này chỉ chứa "Maps".
Bạn có thể phủ lên tài nguyên RotaryService
sau:
- (Android 11 QPR3, Android 11 Car, Android 12)
long_press_ms
: Giá trị số nguyên thể hiện số mili giây cần giữ nút Trung tâm để kích hoạt thao tác nhấn và giữ. Giá trị 0 cho biết bạn nên sử dụng thời gian chờ nhấn và giữ mặc định của hệ thống. Đây là giá trị mặc định.