Przewodnik integracji dla producentów OEM

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:

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. 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:

Kierunek prostopadły
Rysunek 1. Kierunek prostopadły

Powinno to wygenerować następującą sekwencję zdarzeń:

  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

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:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Jeden (1) zatrzask.
  3. 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 :
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (trzy zapadki w kierunku przeciwnym do ruchu wskazówek zegara).
    3. Wyświetlanie docelowe.
    4. 5 ns pomiędzy pierwszym a drugim zaczepem.
    5. 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:

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. 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:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. 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 dla RotaryIME .

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ę w packages/apps/Car/RotaryController
  • Core znajduje się w frameworks/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 :
    1. Pamięć podręczna jest wyłączona.
    2. Pamięć podręczna wygaśnie po pewnym czasie (patrz poniżej).
    3. 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 :
    1. Pamięć podręczna jest wyłączona.
    2. Pamięć podręczna wygasa po pewnym czasie (patrz poniżej).
    3. 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 do rotation_acceleration_3x_ms . Używany do przyspieszenia 2×. Ustaw tę wartość na 2147483647 , 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.

Przycisk z jednolitym tłem
Rysunek 2. Przycisk z jednolitym tłem

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 obszarze FocusArea i jego potomkach. W AOSP ten rysunek jest konturem wokół FocusArea . Producenci OEM mogą zastąpić element rysunkowy car_ui_focus_area_foreground_highlight .
  • car_ui_enable_focus_area_background_highlight : Narysuj podświetlenie na górze FocusArea , ale za jego potomkami. W AOSP to rysowanie jest pełnym wypełnieniem. Producenci OEM mogą zastąpić element rysunkowy car_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ę:

  1. Akcja globalna zdefiniowana przez AccessibilityService . Na przykład GLOBAL_ACTION_BACK .
  2. Kod klucza, taki jak KEYCODE_BACK .
  3. 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 logiczny config_showHeadsUpNotificationOnBottom w frameworks/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ób notification_headsup_card_margin_horizontal dimen w packages/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ących TaskViews lub TaskDisplayAreas . 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.