Na tej stronie opisano, jak przetwarzać wejścia obrotowe w VHAL, konfigurować kompilację tak, aby zawierała usługę rotacyjną, oraz jak dostosowywać obsługę rotacyjną we wszystkich aplikacjach. W przypadku preinstalowanych aplikacji OEM, takich jak program uruchamiający dostarczony przez OEM, zobacz Biblioteka interfejsu użytkownika samochodu (biblioteka car-ui) .
VHAL
Kontroler obrotowy obsługuje następujące działania:
- Poruszaj się w górę, w dół, w lewo i w prawo.
- Obróć zgodnie z ruchem wskazówek zegara i przeciwnie do ruchu wskazówek zegara.
- Naciśnij środkowy przycisk.
- Naciśnij przycisk wstecz.
- Naciśnij przycisk Początek.
- Naciśnij inne przyciski, takie jak Telefon i Media.
Zobacz hardware/interfaces/automotive/vehicle/2.0/types.hal
, aby zapoznać się z dokumentacją właściwości systemu i odpowiadających im int32Values
.
VHAL powinien zająć się następującymi działaniami:
Szturchać
Gdy użytkownik naciśnie kontroler obrotowy w prawo, VHAL powinien użyć właściwości HW_KEY_INPUT
z następującymi int32Values
, aby wysłać zdarzenie do Androida:
-
ACTION_DOWN
-
KEYCODE_SYSTEM_NAVIGATION_RIGHT
- Wyświetlanie docelowe.
Kiedy użytkownik zwolni kontroler obrotowy, VHAL powinien użyć tej samej właściwości i kodu klucza co ACTION_UP
. Popchnięcia w innych kierunkach powinny używać odpowiednich kodów klawiszy.
Nie ma kodów klawiszowych dla przekątnych, ale VHAL może połączyć zdarzenie poziome i pionowe, aby utworzyć przekątną, jeśli sprzęt obsługuje przekątne. Na przykład przesuwanie w górę i w lewo powinno spowodować:
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN
W dowolnej kolejności (i później) zwolnienie pokrętła powinno spowodować:
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
-
HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP
Użytkownik może przesunąć pokrętło w kierunku prostopadłym przed jego zwolnieniem. Na przykład następujący scenariusz:
Powinno to wygenerować następującą sekwencję zdarzeń:
-
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
Nie należy generować powtarzających się zdarzeń, gdy pokrętło jest trzymane w jednym kierunku.
Obracać się
Gdy użytkownik obróci kontroler obrotowy w kierunku zgodnym z ruchem wskazówek zegara o jedną pozycję (kliknięcie), VHAL powinien użyć właściwości HW_ROTARY_INPUT
z następującymi int32Values
, aby wysłać zdarzenie do Androida:
-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- Jeden (1) zatrzask.
- Wyświetlanie docelowe.
Znacznik czasu zdarzenia powinien być ustawiony na czas, który upłynął w nanosekundach.
Obrót o jeden (1) zaczep w kierunku przeciwnym do ruchu wskazówek zegara powinien generować to samo zdarzenie, ale z liczbą -1 dla liczby zaczepów.
Jeżeli w krótkim odstępie czasu pojawia się wiele zatrzymań obrotu w tym samym kierunku, VHAL powinien połączyć te zatrzymania w jedno zdarzenie, aby nie przeciążać systemu zdarzeniami. W tym przypadku znacznikiem czasu zdarzenia powinien być moment wystąpienia pierwszego zatrzymania obrotu. Wartość int32Values
powinna zawierać liczbę nanosekund pomiędzy kolejnymi punktami obrotu.
Na przykład następująca sekwencja obrotów:
- W chwili t0 użytkownik przekręcił jedną zapadkę w kierunku przeciwnym do ruchu wskazówek zegara.
- W czasie t0 + 5 ns użytkownik przekręcił jedną zapadkę w kierunku przeciwnym do ruchu wskazówek zegara.
- W czasie t0 + 8 ns użytkownik przekręcił jedną zapadkę w kierunku przeciwnym do ruchu wskazówek zegara.
powinien wygenerować to zdarzenie:
- Właściwość:
HW_ROTARY_INPUT
- Znacznik czasu:
t0
-
int32Values
:-
ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
- -3 (trzy zapadki w kierunku przeciwnym do ruchu wskazówek zegara).
- Wyświetlanie docelowe.
- 5 ns pomiędzy pierwszym a drugim zaczepem.
- 3 ns między drugim a trzecim zaczepem.
-
Środkowy przycisk
Gdy użytkownik naciśnie przycisk Center, VHAL powinien użyć właściwości HW_KEY_INPUT
z następującymi int32Values
, aby wysłać zdarzenie do Androida:
-
ACTION_DOWN
-
KEYCODE_DPAD_CENTER
- Wyświetlanie docelowe.
Kiedy użytkownik zwolni kontroler obrotowy, VHAL powinien użyć tej samej właściwości i kodu klucza co ACTION_UP
.
Nie generuj powtarzających się zdarzeń, gdy środkowy przycisk jest wciśnięty.
Przycisk powrotu
Gdy użytkownik naciśnie przycisk Wstecz, VHAL powinien użyć właściwości HW_KEY_INPUT
z następującymi int32Values
, aby wysłać zdarzenie do Androida:
-
ACTION_DOWN
-
KEYCODE_BACK
- Wyświetlanie docelowe.
Kiedy użytkownik zwolni kontroler obrotowy, VHAL powinien użyć tej samej właściwości i kodu klucza co ACTION_UP
.
Dopóki środkowy przycisk jest wciśnięty, nie powinny być generowane żadne powtarzające się zdarzenia.
Przycisk strony głównej
Obsługuj przycisk Home tak samo, jak przycisk Wstecz, ale za pomocą KEYCODE_HOME
zamiast KEYCODE_BACK
.
Inne przyciski
Jeśli kontroler obrotowy zawiera dodatkowe przyciski, VHAL może je obsłużyć w dowolny sposób, jaki chce producent OEM, ponieważ nie są one uważane za część pokrętła z punktu widzenia Androida. Zwykle obsługuje się je jak przyciski Wstecz i Strona główna, ale z różnymi kodami klawiszy. Na przykład KEYCODE_CALL
lub KEYCODE_MUSIC
.
Konfiguracja kompilacji
Nawigację Rotary zapewnia usługa ułatwień dostępu o nazwie RotaryService
. Aby uwzględnić tę usługę w obrazie systemu swojego urządzenia, dodaj następujący wiersz do pliku makefile:
PRODUCT_PACKAGES += CarRotaryController
Możesz także dołączyć następujące pakiety do kompilacji debugowania:
-
RotaryPlayground
Aplikacja referencyjna dla urządzeń obrotowych (zobacz RotaryPlayground ). -
RotaryIME
Demo obrotowego edytora IME (zobacz Edytory metod wprowadzania ). -
CarRotaryImeRRO
Nakładka dlaRotaryIME
.
Usługa rotacyjna jest włączana automatycznie po uruchomieniu urządzenia i zmianie użytkownika. Dzięki temu użytkownik może korzystać z pokrętła podczas konfiguracji.
Jeśli używasz tej samej kompilacji do samochodów z kontrolerem obrotowym i bez niego, dodaj CarRotaryController
jak pokazano powyżej, aby w kompilacji znalazł się niezbędny kod. Aby uniemożliwić włączenie usługi obrotowej w samochodach nierotacyjnych, utwórz statyczny RRO, aby nałożyć zasób ciągu rotaryService
w packages/services/Car/service
pustym ciągiem. Będziesz używać tej samej kompilacji, ale będziesz mieć oddzielne konfiguracje produktów dla urządzeń obrotowych i nieobrotowych. Tylko ta ostatnia obejmuje nakładkę.
Dostosowywanie
Producenci OEM mogą dostosować logikę wyszukiwania fokusu, wyróżnienie fokusu i niektóre dodatkowe elementy poprzez nakładki zasobów w następujących lokalizacjach:
- biblioteka car-ui znajduje się w
packages/apps/Car/libs/car-ui-lib
-
RotaryService
znajduje się wpackages/apps/Car/RotaryController
-
Core
znajduje się wframeworks/base/core
Historia szturmowa
Producent OEM może skonfigurować, czy każdy z dwóch typów historii podpowiedzi jest włączony, a jeśli tak, to rozmiar pamięci podręcznej i zasady wygaśnięcia. Wszystko to odbywa się poprzez zastąpienie różnych zasobów biblioteki car-ui.
Pamięć podręczna historii ostrości
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Ta pamięć podręczna dla obszaru FocusArea
przechowuje ostatnio aktywny widok w FocusArea
, dzięki czemu można go skupić podczas powrotu do FocusArea
. Tę pamięć podręczną można skonfigurować, nakładając następujące zasoby biblioteki car-ui:
-
car_ui_focus_history_cache_type
:- Pamięć podręczna jest wyłączona.
- Pamięć podręczna wygaśnie po pewnym czasie (patrz poniżej).
- Pamięć podręczna nigdy nie wygaśnie.
-
car_ui_focus_history_expiration_period_ms
: Ile milisekund przed wygaśnięciem pamięci podręcznej, jeśli typ pamięci podręcznej jest ustawiony na dwa (2) (patrz wyżej).
Pamięć podręczna historii FocusArea
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Ta pamięć podręczna przechowuje historię szturchnięć, dzięki czemu przesuwanie w przeciwnym kierunku może przywrócić fokus do tego samego FocusArea
. Tę pamięć podręczną można skonfigurować, nakładając następujące zasoby biblioteki car-ui:
-
car_ui_focus_area_history_cache_type
:- Pamięć podręczna jest wyłączona.
- Pamięć podręczna wygasa po pewnym czasie (patrz poniżej).
- Pamięć podręczna nigdy nie wygasa.
-
car_ui_focus_area_history_expiration_period_ms
: Ile milisekund przed wygaśnięciem pamięci podręcznej, jeśli typ pamięci podręcznej jest ustawiony na 2 (patrz wyżej). -
car_ui_clear_focus_area_history_when_rotating
: Określa, czy unieważnić pamięć podręczną, gdy użytkownik obróci kontroler.
Obrót
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Producent OEM może zastąpić dwa zasoby całkowite w RotaryService
, aby określić, czy przy rotacji występuje przyspieszenie, na przykład przyspieszenie myszy:
-
rotation_acceleration_3x_ms
: Przedział czasu (w milisekundach) używany do podjęcia decyzji, czy Google powinien przyspieszyć obrót kontrolera w celu zatrzymania obrotu. Jeżeli odstęp pomiędzy tym zaczepem a poprzednim zaczepem obrotu będzie mniejszy od tej wartości, będzie to traktowane jako trzy zaczepy obrotu. Ustaw tę wartość na 2147483647, aby wyłączyć przyspieszenie 3×. -
rotation_acceleration_2x_ms
: Podobna dorotation_acceleration_3x_ms
. Używany do przyspieszenia 2×. Ustaw tę wartość na2147483647
, aby wyłączyć przyspieszenie 2×.
Przyspieszenie działa najlepiej, gdy istnieją indywidualne znaczniki czasu dla każdego punktu obrotu, zgodnie z wymaganiami VHAL. Jeżeli nie są one dostępne, RotaryService
zakłada, że punkty obrotu są równomiernie rozmieszczone.
/** * 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),
Podświetlenie ostrości
Producent OEM może zastąpić domyślne wyróżnienie fokusu w środowisku Android i kilka zasobów podświetlenia fokusu w bibliotece car-ui.
Domyślne podświetlenie ostrości
Struktura systemu Android zapewnia domyślne wyróżnienie fokusu za pomocą selectableItemBackground
. W Theme.DeviceDefault
ten atrybut odnosi się do item_background.xml
w Core
. Producent OEM może nałożyć item_background.xml
, aby zmienić domyślne rysowanie podświetlenia fokusu.
Ten element do rysowania powinien zazwyczaj być StateListDrawable
, który dostosowuje tło w oparciu o różne kombinacje stanów, w tym android:state_focused
i android:state_pressed
. Gdy użytkownik użyje pokrętła do ustawienia ostrości widoku, android:state_focused
będzie miał true
, ale android:state_pressed
będzie miał wartość false
. Jeśli następnie użytkownik naciśnie środkowy przycisk na kontrolerze obrotowym, zarówno android:state_focused
, jak i android:state_pressed
będą true
, dopóki użytkownik przytrzyma przycisk. Kiedy użytkownik zwolni przycisk, tylko android:state_focused
pozostanie true
.
car-ui-library używa motywu pochodzącego z Theme.DeviceDefault
. W rezultacie ta nakładka wpływa na aplikacje korzystające z tej biblioteki i aplikacje korzystające z dowolnego motywu pochodzącego z Theme.DeviceDefault
. Nie będzie to miało wpływu na aplikacje korzystające z niepowiązanego motywu, np. Theme.Material
.
Skoncentruj się na podświetleniu zasobów w bibliotece car-ui
Producent OEM może zastąpić kilka zasobów biblioteki car-ui, aby kontrolować sposób wyświetlania wyróżnienia fokusu w widokach z podświetleniem innym niż prostokątny (np. okrągłym lub w kształcie pigułki) oraz w aplikacjach korzystających z motywu, który nie pochodzi z Theme.DeviceDefault
. Zasoby te powinny zostać nałożone na siebie, tak aby podświetlenie fokusu było spójne z domyślnym rysunkowym podświetleniem fokusu .
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Do wskazania, kiedy widok jest aktywny, ale nie naciśnięty, używane są następujące zasoby:
-
car_ui_rotary_focus_fill_color
: Kolor wypełnienia. -
car_ui_rotary_focus_stroke_color
: Kolor konturu. -
car_ui_rotary_focus_stroke_width
: Grubość konturu.
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Do wskazania, kiedy widok jest aktywny i naciśnięty, używane są następujące zasoby:
-
car_ui_rotary_focus_pressed_fill_color
: Kolor wypełnienia. -
car_ui_rotary_focus_pressed_stroke_color
: Kolor konturu. -
car_ui_rotary_focus_pressed_stroke_width
: Grubość konturu.
Czasami przycisk ma jednolity kolor tła, aby zwrócić na niego uwagę użytkownika, jak w pokazanym przykładzie. Może to sprawić, że podkreślenie ostrości będzie trudne do zauważenia.
W tej sytuacji programista może określić niestandardowe wyróżnienie fokusu za pomocą kolorów dodatkowych :- ( Android 11 QPR3, Android 11 Samochód, 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
Każdy kolor może być przezroczysty, a każdy wymiar może wynosić zero, jeśli na przykład chcesz mieć tylko wypełnienie lub tylko kontur.
Podświetlenie FocusArea
( Android 11 QPR3, Android 11 Samochód, Android 12 )
FocusArea
może narysować dwa rodzaje podświetlenia, gdy jeden z jego elementów podrzędnych jest skupiony. W razie potrzeby oba można stosować w połączeniu. Ta funkcja jest domyślnie wyłączona w AOSP, ale można ją włączyć, zastępując zasoby car-ui-library:
-
car_ui_enable_focus_area_foreground_highlight
: Narysuj podświetlenie na obszarzeFocusArea
i jego potomkach. W AOSP ten rysunek jest konturem wokółFocusArea
. Producenci OEM mogą zastąpić element rysunkowycar_ui_focus_area_foreground_highlight
. -
car_ui_enable_focus_area_background_highlight
: Narysuj podświetlenie na górzeFocusArea
, ale za jego potomkami. W AOSP to rysowanie jest pełnym wypełnieniem. Producenci OEM mogą zastąpić element rysunkowycar_ui_focus_area_background_highlight
.
Redaktorzy metod wprowadzania
Edytory metod wprowadzania (IME) to metody wprowadzania. Na przykład klawiatura ekranowa.
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Producent OEM musi nałożyć zasób ciągu default_touch_input_method
na RotaryService
, aby określić ComponentName
dotykowego edytora IME. Na przykład, jeśli producent OEM korzysta z edytora IME dostarczonego z systemem Android Automotive, powinien określić com.google.android.apps.automotive.inputmethod/.InputMethodService
.
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Jeśli producent OEM utworzył edytor IME specjalnie dla obrotowych, powinien określić jego ComponentName
w zasobie rotary_input_method
. Jeśli ten zasób jest nałożony, określony edytor IME będzie używany za każdym razem, gdy użytkownik wchodzi w interakcję z jednostką główną za pomocą przesuwania, obracania i przycisku środkowego kontrolera obrotowego. Gdy użytkownik dotknie ekranu, zostanie użyty poprzedni edytor IME. Przycisk Wstecz (i inne przyciski na pokrętle) nie mają wpływu na wybór edytora IME. Jeśli ten zasób nie jest nałożony, nie następuje przełączanie edytora IME. Carboard nie obsługuje funkcji obrotowych, więc użytkownik nie może wprowadzać tekstu za pomocą kontrolera obrotowego, jeśli producent OEM nie dostarczył obrotowego edytora IME.
RotaryIME
to demo obrotowego edytora IME. Choć jest to proste, wystarczy wypróbować opisane powyżej automatyczne przełączanie IME. Kod źródłowy RotaryIME
można znaleźć w packages/apps/Car/tests/RotaryIME/
.
Szturchnięcia poza ekranem
Domyślnie, gdy użytkownik próbuje odsunąć się od krawędzi ekranu, nic się nie dzieje. Producent OEM może skonfigurować, co powinno nastąpić dla każdego z czterech kierunków, określając dowolną kombinację:
- Akcja globalna zdefiniowana przez
AccessibilityService
. Na przykładGLOBAL_ACTION_BACK
. - Kod klucza, taki jak
KEYCODE_BACK
. - Zamiar uruchomienia działania reprezentowanego jako adres URL.
( Android 11 QPR3, Android 11 Samochód, Android 12 )
Są one określane poprzez nałożenie następujących zasobów tablicowych w RotaryService
:
-
off_screen_nudge_global_actions
: tablica globalnych akcji do wykonania, gdy użytkownik przesunie się w górę, w dół, w lewo lub w prawo od krawędzi ekranu. Jeśli odpowiednim elementem tej tablicy jest -1, nie jest wykonywana żadna akcja globalna. -
off_screen_nudge_key_codes
: tablica kluczowych kodów zdarzeń kliknięcia, które mają zostać wstrzyknięte, gdy użytkownik przesunie się w górę, w dół, w lewo lub w prawo od krawędzi ekranu. Żadne zdarzenia nie są wstrzykiwane, jeśli odpowiednim elementem tej tablicy jest 0 (KEYCODE_UNKNOWN
). -
off_screen_nudge_intents
: Tablica intencji uruchomienia działania, gdy użytkownik przesunie się w górę, w dół, w lewo lub w prawo od krawędzi ekranu. Żadna czynność nie zostanie uruchomiona, jeśli odpowiedni element tej tablicy jest pusty.
Inne konfiguracje
Powinieneś nałożyć na siebie następujące zasoby RotaryService
:
- ( Android 11 QPR3, Android 11 Samochód, Android 12 )
config_showHeadsUpNotificationOnBottom
: Wartość logiczna określająca, czy powiadomienia heads-up powinny być wyświetlane na dole, a nie na górze. Musi mieć tę samą wartość, co zasób logicznyconfig_showHeadsUpNotificationOnBottom
wframeworks/base/packages/CarSystemUI/res/values/config.xml
- ( Android 11 QPR3, Android 11 Samochód, Android 12 )
notification_headsup_card_margin_horizontal
: Lewy i prawy margines okna powiadomień heads-up. Musi mieć tę samą wartość, co zasóbnotification_headsup_card_margin_horizontal
dimen wpackages/apps/Car/Notification/res/values/dimens.xml
- ( Android 12 )
excluded_application_overlay_window_titles
: Tablica tytułów okien, których nie należy uważać za okna nakładane. Powinno to obejmować tytuły okien aplikacji reprezentującychTaskViews
lubTaskDisplayAreas
. Domyślnie ta lista zawiera tylko „Mapy”.
Możesz nałożyć następujący zasób RotaryService
:
- ( Android 11 QPR3, Android 11 Samochód, Android 12 )
long_press_ms
: Wartość całkowita określająca, przez ile milisekund należy przytrzymać środkowy przycisk, aby wywołać długie naciśnięcie. Zero wskazuje, że należy zastosować domyślny systemowy limit czasu długiego naciśnięcia. Jest to wartość domyślna.