Przewodnik integracji dla producentów OEM

Na tej stronie opisujemy, jak przetwarzać dane z kółka w VHAL, konfigurować kompilację, aby uwzględniała usługę kółka, oraz jak dostosować obsługę kółka we wszystkich aplikacjach. Informacje o wstępnie zainstalowanych aplikacjach OEM, takich jak launcher OEM, znajdziesz w artykule Biblioteka Car UI (car-ui-library).

VHAL

Sterowanie obrotowe umożliwia wykonywanie tych czynności:

  • przesuwać 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.
  • nacisnąć inne przyciski, takie jak Telefon i Multimedie.

W dokumentacji hardware/interfaces/automotive/vehicle/2.0/types.hal znajdziesz informacje o właściwościach systemowych i odpowiadających im int32Values.

VHAL powinien obsługiwać te działania:

Trącenie

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

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Wyświetlacz docelowy.

Gdy użytkownik puszcza kontroler obrotowy, VHAL powinien użyć tej samej właściwości i tego samego kodu klawisza z ACTION_UP. Do stosowania w innych kierunkach należy używać odpowiednich kodów klawiszy.

Nie ma kodów klawiszy dla ruchów po przekątnej, ale VHAL może łączyć ruchy poziomy i pionowy, aby wygenerować ruch po przekątnej, jeśli sprzęt obsługuje takie ruchy. 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 zwolnienie pokrętła powinno wywołać te działania:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

Użytkownik może nacisnąć sterowanie obrotowe w kierunku prostopadłym, a potem puścić. Na przykład w takim przypadku:

Kierunek prostopadły
Rysunek 1. Kierunek prostopadły

Powinna powstać taka sekwencja 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 pokrętła w jednym kierunku nie powinny być generowane żadne zdarzenia powtarzania.

Obróć

Gdy użytkownik obróci pokrętło w kierunku zgodnym z kierunkiem ruchu wskazówek zegara o jeden klik, VHAL powinien użyć właściwości HW_ROTARY_INPUT z tymi wartościami int32Values, aby wysłać zdarzenie do Androida:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. 1 zatrzask.
  3. Wyświetlacz docelowy.

Czas trwania zdarzenia powinien być podany w nanosekundach.

Jedno (1) kliknięcie w lewo powinno wygenerować to samo zdarzenie, ale z liczbą kliknięć równą -1.

Jeśli w krótkim czasie następuje kilka blokad w tym samym kierunku, VHAL powinien połączyć je w jedno zdarzenie, aby nie przeciążać systemu. W tym przypadku sygnatura czasowa zdarzenia powinna odpowiadać pierwszemu punktowi zaczepienia. W int32Values należy podać liczbę nanosekund między kolejnymi punktami zaczepienia obrotu.

Na przykład taka sekwencja obrotów:

  • W czasie t0 użytkownik obrócił pokrętło o jeden zatrzask w przeciwnym kierunku.
  • W czasie t0 + 5 ns użytkownik obrócił pokrętło o jeden zatrzask w przeciwnym kierunku.
  • W czasie t0 + 8 ns użytkownik obrócił pokrętło o jeden skok w przeciwnym kierunku.

powinno wygenerować to zdarzenie:

  • Usługa: HW_ROTARY_INPUT
  • Sygnatura czasowa: t0
  • int32Values:
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (3 zatrzymania w przeciwnym kierunku do ruchu wskazówek zegara).
    3. Wyświetlacz docelowy.
    4. 5 ns między pierwszym a drugim zatrzaskiem.
    5. 3 ns między drugim a trzecim położeniem.

Przycisk środkowy

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

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Wyświetlacz docelowy.

Gdy użytkownik puszcza kontroler obrotowy, VHAL powinien użyć tej samej właściwości i tego samego kodu klucza co w przypadku ACTION_UP.

Nie generuj zdarzeń powtarzania, gdy przycisk środkowy jest przytrzymany.

Przycisk Wstecz

Gdy użytkownik naciśnie przycisk Wstecz, VHAL powinien użyć właściwości HW_KEY_INPUT z tą wartością int32Values, aby wysłać zdarzenie do Androida:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Wyświetlacz docelowy.

Gdy użytkownik puszcza kontroler obrotowy, VHAL powinien użyć tej samej właściwości i tego samego kodu klucza co w przypadku ACTION_UP.

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

Przycisk Ekran główny

Użyj przycisku ekranu głównego tak samo jak przycisku Wstecz, ale z użyciem KEYCODE_HOME zamiast KEYCODE_BACK.

Inne przyciski

Jeśli kontroler obrotowy zawiera dodatkowe przyciski, VHAL może je obsługiwać w dowolny sposób, ponieważ z perspektywy Androida nie są one częścią kontrolera obrotowego. Są one zwykle obsługiwane jak przyciski Wstecz i Ekran główny, ale mają inne kody klawiszy. Na przykład KEYCODE_CALL lub KEYCODE_MUSIC.

Konfiguracja kompilacji

Nawigacja za pomocą pierścienia jest obsługiwana przez usługę ułatwień dostępu o nazwie RotaryService. Aby uwzględnić tę usługę w pliku obrazu systemu na urządzeniu, dodaj ten wiersz do makefile:

PRODUCT_PACKAGES += CarRotaryController

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

  • RotaryPlayground Aplikacja referencyjna dla pokrętła (patrz RotaryPlayground).
  • RotaryIME Demo edytora metody wprowadzania z pokrętłem (patrz Edytory metody wprowadzania).
  • CarRotaryImeRRO Nakładka dla RotaryIME.

Usługa obrotowa jest włączana automatycznie po uruchomieniu urządzenia i podczas przełączania użytkowników. Dzięki temu użytkownik może korzystać z kontrolera obrotowego podczas konfiguracji.

Jeśli używasz tej samej wersji dla samochodów z kontrolerem obrotowym i bez niego, dodaj CarRotaryController, jak pokazano powyżej, aby uwzględnić w wersji odpowiedni kod. Aby zapobiec włączeniu usługi obrotowej w przypadku pojazdów bez funkcji obrotowej, utwórz stałą regułę RRO, aby zastąpić zasób ciągu znaków rotaryService w pliku packages/services/Car/service pustym ciągiem znaków. Użyjesz tej samej wersji, ale będziesz mieć osobne konfiguracje produktów na urządzenia z klawiaturą obrotową i bez klawiatury obrotowej. Tylko w tym drugim przypadku jest nałożona.

Dostosowywanie

Producenci OEM mogą dostosować logikę znajdowania punktu skupienia, podświetlenie punktu skupienia i niektóre dodatkowe elementy za pomocą nakładek zasobów w tych miejscach:

  • 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 powiadomień

Producent OEM może skonfigurować, czy oba typy historii podpowiedzi są włączone, a jeśli tak, określić rozmiar pamięci podręcznej i zasady wygasania. Wszystko to jest realizowane przez zastąpienie różnych zasobów biblioteki interfejsu użytkownika samochodu.

Pamięć podręczna historii Focus

(Android 11 QPR3, Android 11 Car, Android 12)
Ten element pamięci podręcznej FocusArea przechowuje ostatnio używany widok w FocusArea, aby można było go wybrać, gdy wrócisz do FocusArea. Ten bufor 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 niż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 jej typ ma wartość 2 (patrz wyżej).

Pamięć podręczna historii obszaru na pierwszym planie

(Android 11 QPR3, Android 11 Car, Android 12)
Ten bufor przechowuje historię podpowiedzi, dzięki czemu przesunięcie w przeciwnym kierunku może przywrócić fokus do tego samego FocusArea. Ten bufor można skonfigurować, nakładając te zasoby z biblioteki car-ui-library:

  • car_ui_focus_area_history_cache_type:
    1. Pamięć podręczna jest wyłączona.
    2. Pamięć podręczna traci ważność 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 jej typ ma wartość 2 (patrz wyżej).
  • car_ui_clear_focus_area_history_when_rotating: czy bufor powinien być anulowany, gdy użytkownik obróci kontroler.

Obrót

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

  • rotation_acceleration_3x_ms: przedział czasu (w milisekundach) używany do określania, czy Google powinno przyspieszyć obrót kontrolera w przypadku zablokowania obrotu. Jeśli odstęp między tym zatrzaskiem a poprzednim zatrzaskiem obrotu jest mniejszy niż ta wartość, będzie traktowany jako 3 zatrzaski obrotu. Aby wyłączyć przyspieszenie 3×, ustaw tę wartość na 2147483647.
  • rotation_acceleration_2x_ms: podobny do rotation_acceleration_3x_ms. Służy do przyspieszania 2-krotnego. Aby wyłączyć przyspieszenie 2x, ustaw tę wartość na 2147483647.

Akceleracja działa najlepiej, gdy dla każdego punktu zaczepienia obrotu są dostępne osobne sygnatury czasowe, zgodnie z wymaganiami VHAL. Jeśli te wartości są niedostępne, RotaryService zakłada, że punkty zaczepowe 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 punktu skupienia w ramach Androida i kilka zasobów wyróżnienia punktu skupienia w bibliotece ui-car.

Domyślne podświetlenie fokusu

Platforma Androida udostępnia domyślne wyróżnienie punktu skupienia za pomocą atrybutu selectableItemBackground. W pliku Theme.DeviceDefault ten atrybut odnosi się do elementu item_background.xml w pliku Core. Producent OEM może nałożyć item_background.xml, aby zmienić domyślny element rysowany podświetlenia punktu zainteresowania.

Ten element rysowalny powinien zwykle być elementem StateListDrawable, który dostosowuje tło na podstawie różnych kombinacji stanów, w tym android:state_focusedandroid:state_pressed. Gdy użytkownik użyje kontrolera obrotowego, aby ustawić punkt skupienia widoku, android:state_focused będzie true, a android:state_pressed będzie false. Jeśli użytkownik naciśnie przycisk środkowy na kontrolerze obrotowym, funkcje android:state_focusedandroid:state_pressed będą działać jako true, dopóki przycisk jest wciśnięty. Gdy użytkownik puści przycisk, pozostanie tylko android:state_focusedtrue.

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

Zasoby podświetlenia w komponentach car-ui-library

Producent OEM może zastąpić kilka zasobów z biblioteki interfejsu użytkownika samochodu, aby kontrolować wygląd wyróżnienia punktu skupienia w widokach z wyróżnieniem punktu skupienia o kształcie innym niż prostokąt (np. okrągły lub w kształcie pigułki) oraz w aplikacjach, które korzystają z motywu niewywodzącego się z Theme.DeviceDefault. Te zasoby powinny być nałożone w taki sposób, aby wyróżnienie było zgodne z domyślnym wyróżnieniem zaznaczenia.

(Android 11 QPR3, Android 11 Car, Android 12)
Aby wskazać, że widok jest aktywny, ale nie wciśnięty, używaj tych zasobów:

  • car_ui_rotary_focus_fill_color: kolor wypełnienia.
  • car_ui_rotary_focus_stroke_color: kolor konturu.
  • car_ui_rotary_focus_stroke_width: grubość obrysu.

(Android 11 QPR3, Android 11 Car, Android 12)
Aby wskazać, kiedy widok jest skupiony i wciś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ść obrysu.

Czasami przycisk ma jednolity kolor tła, aby zwrócić uwagę użytkownika, jak w przypadku pokazanym na przykładzie. Może to utrudnić dostrzeżenie podświetlenia.

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

W takim przypadku deweloper może określić niestandardowe podświetlenie punktu skupienia za pomocą kolorów dodatkowych:
  • (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 z kolorów może być przezroczysty, a każdy wymiar może być równy 0, jeśli np. chcesz użyć tylko wypełnienia lub tylko konturu.

Wyróżnienie obszaru zaznaczenia

(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea może wyświetlać 2 typy wyróżnień, gdy jeden z jego potomków jest aktywny. W razie potrzeby możesz używać obu tych metod jednocześnie. Ta funkcja jest domyślnie wyłączona w AOSP, ale można ją włączyć, zastępując zasoby biblioteki interfejsu użytkownika samochodu:

  • car_ui_enable_focus_area_foreground_highlight: narysuj wyróżnienie na wierzchołku FocusArea i jego potomków. W AOSP ten zasób graficzny jest obrysemFocusArea. Producenci OEM mogą zastąpić ten obrazek.car_ui_focus_area_foreground_highlight
  • car_ui_enable_focus_area_background_highlight: zaznacz FocusArea, ale nie jego potomków. W AOSP ten zasób graficzny ma jednolitą wypełnienie. Producenci OEM mogą zastąpić car_ui_focus_area_background_highlight rysunek.

Edytory metody wprowadzania

Edytory metody wprowadzania (IME) to metody wprowadzania. Może to być na przykład klawiatura ekranowa.

(Android 11 QPR3, Android 11 Car, Android 12)
OEM musi zastąpić zasób ciągu znaków default_touch_input_methodRotaryService, aby określić ComponentName interfejsu IME opartego na dotyku. Jeśli na przykład OEM używa IME dostarczonego z Androidem Automotive, powinien określić wartość com.google.android.apps.automotive.inputmethod/.InputMethodService.

(Android 11 QPR3, Android 11 Car, Android 12)
Jeśli producent OEM stworzył IME specjalnie dla klawiatury obrotowej, powinien podać jego ComponentName w zasobach rotary_input_method. Jeśli ten zasób jest nałożony, określony interfejs IME jest używany, gdy użytkownik wchodzi w interakcję z główną jednostką za pomocą przycisku obracanego, przycisku przesuwania i przycisku środkowego. Gdy użytkownik dotknie ekranu, zostanie użyte poprzednie IME. Przycisk Wstecz (i inne przyciski na kontrolerze obrotowym) nie mają wpływu na wybór IME. Jeśli ten zasób nie jest nałożony, nie następuje przełączanie IME. Carboard nie obsługuje pokrętła, więc użytkownik nie może wpisywać tekstu za pomocą pokrętła sterującego, jeśli OEM nie udostępnił IME z pokrętłem.

RotaryIME to demonstracyjny IME z pokrętłem. Jest to wersja podstawowa, ale wystarcza do wypróbowania automatycznego przełączania IME opisanego powyżej. Kod źródłowy RotaryIME znajdziesz w pliku packages/apps/Car/tests/RotaryIME/.

Powiadomienia poza ekranem

Domyślnie, gdy użytkownik próbuje przesunąć element poza krawędź ekranu, nic się nie dzieje. Producent OEM może skonfigurować, co ma się dziać w przypadku każdego z tych 4 kierunków, podając dowolną kombinację:

  1. Działanie globalne zdefiniowane przez AccessibilityService. Na przykład:GLOBAL_ACTION_BACK.
  2. klucza kodu, np. KEYCODE_BACK;
  3. intencja uruchomienia aktywności reprezentowanej jako adres URL;

(Android 11 QPR3, Android 11 Car, Android 12)
Te wersje są określane przez nakładanie tych zasobów tablic na RotaryService:

  • off_screen_nudge_global_actions: tablica działań globalnych wykonywanych, gdy użytkownik przesunie palcem w górę, w dół, w lewo lub w prawo od krawędzi ekranu. Jeśli odpowiedni element tego tablic ma wartość -1, nie wykonuje się żadnego działania globalnego.
  • off_screen_nudge_key_codes: tablica kodów klawiszy zdarzeń kliknięcia, które mają być wstawiane, gdy użytkownik przesunie palcem w górę, w dół, w lewo lub w prawo poza krawędź ekranu. Żadne zdarzenia nie są wstrzykiwane, jeśli odpowiedni element tego tablic ma wartość 0 (KEYCODE_UNKNOWN).
  • off_screen_nudge_intents: tablica intencji służących do 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 tablicy jest pusty, nie uruchamia się żadna aktywność.

Inne konfiguracje

Należy nałożyć 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 na dole, a nie u góry. Musi mieć tę samą wartość co zasób typu config_showHeadsUpNotificationOnBottom (wartość logiczna) w sekcji frameworks/base/packages/CarSystemUI/res/values/config.xml.
  • (Android 11 QPR3, Android 11 Car, Android 12)
    notification_headsup_card_margin_horizontal: marginesy lewy i prawy okna powiadomień wyskakujących. Musi mieć taką samą wartość jak zasób notification_headsup_card_margin_horizontal w pliku dimen w pliku packages/apps/Car/Notification/res/values/dimens.xml.
  • (Android 12)
    excluded_application_overlay_window_titles: tablica zawierająca tytuły okien, które nie powinny być traktowane jako okna nakładki. Powinny one obejmować tytuły okien aplikacji reprezentujących TaskViews lub TaskDisplayAreas. Domyślnie zawiera ona tylko „Mapy”.

Możesz nałożyć na dane z usług RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    long_press_ms: wartość całkowita określająca, przez ile milisekund przytrzymanie przycisku środkowego powoduje długie naciśnięcie. Wartość 0 oznacza, że należy użyć domyślnego limitu czasu długiego naciśnięcia. jest to wartość domyślna