Przewodnik integracji dla producentów OEM

Na tej stronie dowiesz się, jak przetwarzać dane wejściowe pokrętła w VHAL, skonfigurować kompilację, aby uwzględniała usługę pokrętła, i jak dostosowywać działanie pokrętła we wszystkich aplikacjach. W przypadku preinstalowanych aplikacji OEM, takich jak launcher dostarczony przez OEM, zapoznaj się z informacjami o bibliotece interfejsu samochodu (car-ui-library).

VHAL

Kontroler obrotowy obsługuje te działania:

  • Posuń w górę, w dół, w lewo i w prawo.
  • Obróć w prawo i w lewo.
  • Naciśnij przycisk środkowy.
  • Naciśnij przycisk Wstecz.
  • Naciśnij przycisk strony głównej.
  • Naciśnij inne przyciski, np. Telefon i Media.

Dokumentację właściwości systemu i odpowiadających im int32Values znajdziesz w sekcji hardware/interfaces/automotive/vehicle/2.0/types.hal.

VHAL powinna obsługiwać te działania:

Ponaglenie

Gdy użytkownik przesunie pokrętło w prawo, VHAL powinien użyć właściwości HW_KEY_INPUT z tym int32Values, aby wysłać zdarzenie do Androida:

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Docelowy wyświetlacz.

Gdy użytkownik zwolni pokrętło, VHAL powinien użyć tej samej właściwości i tego samego kodu klucza z ACTION_UP. W przypadku innych kierunków należy używać odpowiednich kodów klawiszy.

Nie ma kodów klawiszy dla przekątnych, ale VHAL może łączyć zdarzenia poziome i pionowe, aby uzyskać przekątną, jeśli sprzęt ją obsługuje. Na przykład przesunięcie w górę i w lewo powinno dać taki efekt:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN

W dowolnej kolejności (a następnie) zwolnienie kontrolera obrotowego powinno spowodować:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

Użytkownik może nacisnąć pokrętło w kierunku prostopadłym, a następnie je zwolnić. Na przykład w takiej sytuacji:

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

Podczas przytrzymywania kontrolera obrotowego w jednym kierunku nie powinny być generowane żadne zdarzenia repeat.

Obróć

Gdy użytkownik obróci pokrętło o jeden stopień w prawo (kliknięcie), VHAL powinien użyć właściwości HW_ROTARY_INPUT z tym int32Values, aby wysłać zdarzenie do Androida:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Jeden (1) zatrzask.
  3. Docelowy wyświetlacz.

Sygnatura czasowa zdarzenia powinna być ustawiona na czas, który upłynął w nanosekundach.

Obrót o 1 stopień w kierunku przeciwnym do ruchu wskazówek zegara powinien wygenerować to samo zdarzenie, ale z wartością -1 w przypadku liczby stopni.

Jeśli kilka pozycji obrotu w tym samym kierunku wystąpi szybko po sobie, VHAL powinien połączyć je w jedno zdarzenie, aby nie przeciążać systemu. W takim przypadku sygnatura czasowa zdarzenia powinna odpowiadać momentowi pierwszego zatrzymania obrotu. Wartość int32Values powinna zawierać liczbę nanosekund między kolejnymi zatrzymaniami obrotu.

Na przykład ta sekwencja obrotów:

  • W momencie t0 użytkownik obrócił pokrętło o 1 stopień w kierunku przeciwnym do ruchu wskazówek zegara.
  • W momencie t0 + 5 ns użytkownik obrócił pokrętło o 1 kliknięcie w kierunku przeciwnym do ruchu wskazówek zegara.
  • W momencie t0 + 8 ns użytkownik obrócił pokrętło o 1 stopień w kierunku przeciwnym do ruchu wskazówek zegara.

powinno wygenerować to zdarzenie:

  • Usługa: HW_ROTARY_INPUT
  • Sygnatura czasowa: t0
  • int32Values:
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. –3 (trzy kliknięcia w lewo).
    3. Docelowy wyświetlacz.
    4. 5 ns między pierwszym a drugim zatrzaskiem.
    5. 3 ns między drugim a trzecim punktem oporu.

Przycisk środkowy

Gdy użytkownik naciśnie przycisk środkowy, VHAL powinien użyć HW_KEY_INPUTwłaściwości z tymi int32Values, aby wysłać zdarzenie do Androida:

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Docelowy wyświetlacz.

Gdy użytkownik zwolni pokrętło, VHAL powinien użyć tej samej właściwości i tego samego kodu klawisza z ACTION_UP.

Nie generuj powtarzających się zdarzeń, gdy przycisk środkowy jest przytrzymywany.

Przycisk Wstecz

Gdy użytkownik naciśnie przycisk Wstecz, VHAL powinien użyć HW_KEY_INPUTwłaściwości z tym int32Values, aby wysłać zdarzenie do Androida:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Docelowy wyświetlacz.

Gdy użytkownik zwolni pokrętło, VHAL powinien użyć tej samej właściwości i tego samego kodu klawisza z ACTION_UP.

Podczas przytrzymywania przycisku środkowego nie powinny być generowane żadne zdarzenia powtarzane.

przycisk strony głównej

Postępuj tak samo jak w przypadku przycisku Wstecz, ale zamiast KEYCODE_BACK użyj KEYCODE_HOME.

Inne przyciski

Jeśli pokrętło zawiera dodatkowe przyciski, VHAL może je obsługiwać w dowolny sposób, ponieważ z perspektywy Androida nie są one uważane za część pokrętła. Zwykle działają one jak przyciski Wstecz i Ekran główny, ale mają inne kody klawiszy. Na przykład KEYCODE_CALL lub KEYCODE_MUSIC.

Konfiguracja kompilacji

Nawigacja obrotowa jest dostępna dzięki usłudze ułatwień dostępu o nazwie RotaryService. Aby uwzględnić tę usługę w obrazie systemu na urządzeniu, dodaj ten wiersz do pliku makefile:

PRODUCT_PACKAGES += CarRotaryController

W wersjach debugowania możesz też uwzględnić te pakiety:

Usługa obrotowa jest włączana automatycznie podczas uruchamiania urządzenia i gdy użytkownik przełącza się na inne konto. Dzięki temu użytkownik może korzystać z kontrolera obrotowego podczas konfiguracji.

Jeśli używasz tej samej kompilacji w przypadku samochodów z kontrolerem obrotowym i bez niego, dodaj CarRotaryController, jak pokazano powyżej, aby w kompilacji znalazł się niezbędny kod. Aby zapobiec włączaniu usługi obrotowej w samochodach bez tej funkcji, utwórz statyczną nakładkę RRO, która zastąpi ciąg rotaryService w zasobie 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 ten drugi zawiera nakładkę.

Dostosowywanie

Producenci OEM mogą dostosowywać logikę wyszukiwania ostrości, wyróżnienie ostrości i niektóre dodatkowe elementy za pomocą nakładek na zasoby w tych lokalizacjach:

  • Biblioteka car-ui-library 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 ponagleń

Producent OEM może skonfigurować, czy każdy z 2 rodzajów historii przypomnień jest włączony, a jeśli tak, to rozmiar pamięci podręcznej i zasady wygasania. Odbywa się to przez zastąpienie różnych zasobów biblioteki car-ui-library.

Pamięć podręczna historii ostrości

(Android 11 QPR3, Android 11 Car, Android 12)
Ta pamięć podręczna FocusArea przechowuje ostatnio zaznaczony widok w FocusArea, aby można było go zaznaczyć po powrocie do FocusArea. Pamięć podręczną można skonfigurować, nakładając te zasoby biblioteki interfejsu użytkownika samochodu:

  • 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: liczba milisekund przed wygaśnięciem pamięci podręcznej, jeśli typ pamięci podręcznej jest ustawiony na 2 (patrz wyżej).

Pamięć podręczna historii FocusArea

(Android 11 QPR3, Android 11 Car, Android 12)
Ta pamięć podręczna przechowuje historię podpowiedzi, dzięki czemu podpowiedź w przeciwnym kierunku może przywrócić fokus do tego samego FocusArea. Tę pamięć podręczną można skonfigurować, nakładając te zasoby biblioteki interfejsu samochodowego:

  • car_ui_focus_area_history_cache_type:
    1. Pamięć podręczna jest wyłączona.
    2. Pamięć podręczna wygasa po pewnym czasie (patrz niżej).
    3. Pamięć podręczna nigdy nie wygasa.
  • car_ui_focus_area_history_expiration_period_ms: liczba 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: czy unieważnić pamięć podręczną, gdy użytkownik obróci kontroler.

Obrót

(Android 11 QPR3, Android 11 Car, Android 12)
Producent OEM może zastąpić 2 zasoby całkowite w RotaryService, aby określić, czy występuje przyspieszenie, np. przyspieszenie myszy, w przypadku obrotu:

  • rotation_acceleration_3x_ms: Przedział czasu (w milisekundach) używany do określania, czy Google ma przyspieszyć obrót kontrolera w przypadku zatrzasku obrotu. Jeśli odstęp między tym a poprzednim punktem zatrzymania obrotu jest mniejszy od tej wartości, zostanie on potraktowany jako 3 punkty zatrzymania obrotu. Aby wyłączyć akcelerację 3×, ustaw tę wartość na 2147483647.
  • rotation_acceleration_2x_ms: podobne do rotation_acceleration_3x_ms. Używany do 2-krotnego przyspieszenia. Ustaw tę wartość na 2147483647, aby wyłączyć 2-krotne przyspieszenie.

Przyspieszenie działa najlepiej, gdy dla każdego punktu obrotu są dostępne indywidualne sygnatury czasowe, co jest wymagane przez VHAL. Jeśli nie są dostępne, RotaryService zakłada, że punkty zatrzymania obrotu są rozmieszczone równomiernie.

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

Wyróżnienie zaznaczenia

Producent OEM może zastąpić domyślne wyróżnienie fokusu w platformie Android i kilka zasobów wyróżnienia fokusu w bibliotece car-ui-library.

Domyślne podświetlenie fokusu

Platforma Androida udostępnia domyślne wyróżnienie fokusu za pomocą atrybutu 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ślny rysunek wyróżnienia fokusu.

Zwykle powinien to być obiekt rysowalny StateListDrawable, który dostosowuje tło w zależności od różnych kombinacji stanów, w tym android:state_focusedandroid:state_pressed. Gdy użytkownik użyje kontrolera obrotowego do ustawienia ostrości widoku, wartość android:state_focused będzie wynosić true, a wartość android:state_pressed będzie wynosić false. Jeśli użytkownik naciśnie przycisk środkowy na kontrolerze obrotowym, oba przyciski android:state_focusedandroid:state_pressed będą true, dopóki użytkownik będzie przytrzymywać przycisk. Gdy użytkownik puści przycisk, pozostanie tylko android:state_focusedtrue.

car-ui-library używa motywu pochodzącego z Theme.DeviceDefault. W rezultacie ta nakładka wpływa na aplikacje, które korzystają z tej biblioteki, oraz na aplikacje, które korzystają z dowolnego motywu pochodzącego z Theme.DeviceDefault. Nie wpłynie to na aplikacje, które używają niezwiązanego motywu, np. Theme.Material.

Zasoby wyróżnienia fokusu w bibliotece car-ui-library

Producent OEM może zastąpić kilka zasobów biblioteki car-ui, aby kontrolować wygląd wyróżnienia fokusu na widokach z wyróżnieniem fokusu o kształcie innym niż prostokątny (np. okrągłym lub w kształcie pigułki) oraz w aplikacjach, które używają motywu niepochodzącego z Theme.DeviceDefault. Te zasoby powinny być nakładane tak, aby wyróżnienie zaznaczenia było zgodne z elementem rysowalnym domyślnego wyróżnienia zaznaczenia.

(Android 11 QPR3, Android 11 Car, Android 12)
Do wskazywania, że widok jest aktywny, ale nie jest naciśnięty, używane są te 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 Car, Android 12)
Do wskazywania, kiedy widok jest zaznaczony i naciśnięty, używane są te 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 przyciągnąć uwagę użytkownika, jak w pokazanym przykładzie. Może to utrudniać dostrzeżenie wyróżnienia fokusu.

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

W takiej sytuacji deweloper może określić niestandardowe wyróżnienie za pomocą dodatkowych kolorów:
  • (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

Każdy kolor może być przezroczysty, a każdy wymiar może mieć wartość zero, jeśli na przykład chcesz użyć tylko wypełnienia lub tylko konturu.

Wyróżnienie FocusArea

(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea może rysować 2 rodzaje wyróżnienia, gdy jeden z jego elementów podrzędnych jest aktywny. W razie potrzeby można używać obu tych funkcji jednocześnie. Ta funkcja jest domyślnie wyłączona w AOSP, ale można ją włączyć, zastępując zasoby biblioteki car-ui:

  • car_ui_enable_focus_area_foreground_highlight: narysuj wyróżnienie na elemencie FocusArea i jego elementach podrzędnych. W AOSP ten element rysowalny jest konturem wokół ikony FocusArea. Producenci OEM mogą zastąpić element rysowalny car_ui_focus_area_foreground_highlight.
  • car_ui_enable_focus_area_background_highlight: narysuj wyróżnienie na elemencie FocusArea, ale za jego elementami podrzędnymi. W AOSP ten element rysowalny jest wypełniony jednolitym kolorem. Producenci OEM mogą zastąpić element rysowalny car_ui_focus_area_background_highlight.

Edytory metod wprowadzania

Edytory metody wprowadzania (IME) to metody wprowadzania. na przykład klawiatura ekranowa;

(Android 11 QPR3, Android 11 Car, Android 12)
Producent OEM musi nałożyć zasób tekstowy default_touch_input_method na RotaryService, aby określić ComponentName klawiatury ekranowej opartej na dotyku. Jeśli na przykład producent OEM używa edytora IME dostarczonego z Androidem Automotive, powinien określić com.google.android.apps.automotive.inputmethod/.InputMethodService.

(Android 11 QPR3, Android 11 Car, Android 12)
Jeśli producent OEM utworzył edytor IME specjalnie do sterowania obrotowego, powinien określić jego ComponentName w zasobie rotary_input_method. Jeśli ten zasób jest nakładany, określony edytor IME jest używany, gdy użytkownik wchodzi w interakcję z jednostką główną za pomocą pokrętła, obracając je, przesuwając lub naciskając przycisk środkowy. Gdy użytkownik dotknie ekranu, zostanie użyta poprzednia metoda wprowadzania. Przycisk Wstecz (i inne przyciski na kontrolerze obrotowym) nie mają wpływu na wybór IME. Jeśli ten zasób nie jest nakładany, nie następuje przełączanie IME. Cardboard nie obsługuje pokrętła, więc użytkownik nie może wprowadzać tekstu za pomocą pokrętła, jeśli producent OEM nie udostępnił klawiatury IME z pokrętłem.

RotaryIME to demonstracyjna klawiatura IME z pokrętłem. Chociaż jest to podstawowa funkcja, wystarczy, aby wypróbować automatyczne przełączanie IME opisane powyżej. Kod źródłowy RotaryIME znajdziesz w packages/apps/Car/tests/RotaryIME/.

Ponaglenia poza ekranem

Domyślnie, gdy użytkownik spróbuje przesunąć kursor poza krawędź ekranu, nic się nie stanie. Producent OEM może skonfigurować, co ma się wydarzyć w każdym z 4 kierunków, określając dowolną kombinację:

  1. Działanie globalne zdefiniowane przez AccessibilityService. Na przykład: GLOBAL_ACTION_BACK.
  2. kod klucza, np. KEYCODE_BACK;
  3. Intencja uruchomienia działania przedstawiona jako adres URL.

(Android 11 QPR3, Android 11 Car, Android 12)
Są one określone przez nakładanie tych zasobów tablicy w RotaryService:

  • off_screen_nudge_global_actions: tablica działań globalnych do wykonania, gdy użytkownik przesunie palcem w górę, w dół, w lewo lub w prawo poza krawędź ekranu. Jeśli odpowiedni element tej tablicy ma wartość -1, nie jest wykonywane żadne działanie globalne.
  • off_screen_nudge_key_codes: tablica kodów klawiszy zdarzeń kliknięcia do wstrzyknięcia, gdy użytkownik przesunie palcem w górę, w dół, w lewo lub w prawo poza krawędź ekranu. Jeśli odpowiedni element tej tablicy ma wartość 0 (KEYCODE_UNKNOWN), nie są wstrzykiwane żadne zdarzenia.
  • off_screen_nudge_intents: tablica intencji uruchamiania działania, gdy użytkownik przesunie palcem w górę, w dół, w lewo lub w prawo od krawędzi ekranu. Jeśli odpowiedni element tej tablicy jest pusty, nie jest uruchamiana żadna aktywność.

Inne konfiguracje

Nałóż na siebie te zasoby RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    config_showHeadsUpNotificationOnBottom: wartość logiczna określająca, czy powiadomienia typu heads-up mają być wyświetlane u dołu, a nie u góry. Musi mieć tę samą wartość co zasób logiczny config_showHeadsUpNotificationOnBottomframeworks/base/packages/CarSystemUI/res/values/config.xml.
  • (Android 11 QPR3, Android 11 Car, Android 12)
    notification_headsup_card_margin_horizontal: lewy i prawy margines okna powiadomienia heads-up. Musi mieć taką samą wartość jak 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óre nie powinny być traktowane jako okna nakładki. Powinny one zawierać tytuły okien aplikacji, które reprezentują TaskViews lub TaskDisplayAreas. Domyślnie ta lista zawiera tylko „Mapy”.

Możesz nałożyć na siebie te zasoby RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    long_press_ms: wartość całkowita określająca, ile milisekund należy przytrzymać przycisk środkowy, aby wywołać długie naciśnięcie. Wartość 0 oznacza, że należy użyć domyślnego czasu oczekiwania systemu na długie naciśnięcie. Jest to wartość domyślna.