Guida all'integrazione per gli OEM

Questa pagina descrive come elaborare gli input rotatori in VHAL, configurare la compilazione per includere il servizio rotatorio e come personalizzare l'esperienza rotatoria in tutte le app. Per le app OEM preinstallate, ad esempio un Avvio app fornito dall'OEM, consulta Libreria dell'interfaccia utente dell'auto (car-ui-library).

VHAL

Un controllo rotativo supporta le seguenti azioni:

  • Sposta verso l'alto, il basso, a sinistra e a destra.
  • Ruota in senso orario e antiorario.
  • Premi il tasto centrale.
  • Premi il tasto Indietro.
  • Premi il pulsante Home.
  • Premi altri pulsanti, ad esempio Telefono e Contenuti multimediali.

Consulta hardware/interfaces/automotive/vehicle/2.0/types.hal per la documentazione relativa alle proprietà di sistema e ai int32Values corrispondenti.

Il VHAL deve gestire queste azioni:

Sollecito

Quando l'utente spinge il controllo rotativo verso destra, VHAL deve utilizzare la proprietà HW_KEY_INPUT con il seguente int32Values per inviare un evento ad Android:

  1. ACTION_DOWN
  2. KEYCODE_SYSTEM_NAVIGATION_RIGHT
  3. Display target.

Quando l'utente rilascia il controller rotativo, il VHAL deve utilizzare la stessa proprietà e lo stesso codice a chiave con ACTION_UP. Per i movimenti in altre direzioni devono essere utilizzati i codici a tasti corrispondenti.

Non esistono codici tasti per le diagonali, ma VHAL può combinare un evento orizzontale e verticale per produrre una diagonale se l'hardware supporta le diagonali. Ad esempio, spingendo verso l'alto e verso sinistra dovresti ottenere:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_DOWN
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_DOWN

In entrambi gli ordini (e successivamente), il rilascio del controllore rotativo dovrebbe produrre:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

L'utente può spingere il controllo rotativo in una direzione perpendicolare prima di rilasciarlo. Ad esempio, il seguente scenario:

Direzione perpendicolare
Figura 1. Direzione perpendicolare

Dovrebbe generarsi la seguente sequenza di eventi:

  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

Non devono essere generati eventi di ripetizione mentre il controllo rotativo viene tenuto in una direzione.

Ruota

Quando l'utente ruota il controllo rotativo in senso orario di un dente (clic), VHAL deve utilizzare la proprietà HW_ROTARY_INPUT con il seguente int32Values per inviare un evento ad Android:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Una (1) detent.
  3. Display target.

Il timestamp dell'evento deve essere impostato sul tempo trascorso in nanosecondi.

Una rotazione antioraria di un (1) dente deve generare lo stesso evento, ma con -1 per il numero di dente.

Se si verificano più scatti di rotazione nella stessa direzione in rapida successione, il VHAL deve combinare gli scatti in un singolo evento per non sovraccaricare il sistema di eventi. In questo caso, il timestamp dell'evento deve corrispondere al momento in cui si è verificato il primo scatto della rotazione. int32Values deve includere il numero di nanosecondi tra scatti consecutivi di rotazione.

Ad esempio, la seguente sequenza di rotazioni:

  • Al momento t0, l'utente ha ruotato di un dente antiorario.
  • Al momento t0 + 5 ns, l'utente ha ruotato un dente antiorario.
  • Al momento t0 + 8 ns, l'utente ha ruotato di un dente antiorario.

dovrebbe generare questo evento:

  • Proprietà: HW_ROTARY_INPUT
  • Timestamp: t0
  • int32Values:
    1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
    2. -3 (tre scatti in senso antiorario).
    3. Display target.
    4. 5 ns tra il primo e il secondo dente di arresto.
    5. 3 ns tra il secondo e il terzo dente.

Pulsante centrale

Quando l'utente preme il pulsante centrale, VHAL deve utilizzare la proprietà HW_KEY_INPUT con il seguente int32Values per inviare un evento ad Android:

  1. ACTION_DOWN
  2. KEYCODE_DPAD_CENTER
  3. Display target.

Quando l'utente rilascia il controller rotativo, il VHAL deve utilizzare la stessa proprietà e lo stesso codice a chiave con ACTION_UP.

Non generare eventi di ripetizione quando il tasto centrale viene tenuto premuto.

Pulsante Indietro

Quando l'utente preme il pulsante Indietro, VHAL deve utilizzare la proprietà HW_KEY_INPUT con il seguente int32Values per inviare un evento ad Android:

  1. ACTION_DOWN
  2. KEYCODE_BACK
  3. Display target.

Quando l'utente rilascia il controller rotativo, il VHAL deve utilizzare la stessa proprietà e lo stesso codice a chiave con ACTION_UP.

Non devono essere generati eventi di ripetizione mentre il tasto centrale è premuto.

Pulsante Home

Usa il pulsante Home come faresti con il pulsante Indietro, ma con KEYCODE_HOME anziché KEYCODE_BACK.

Altri pulsanti

Se il controller rotativo include pulsanti aggiuntivi, il VHAL può gestirli come preferisce l'OEM, poiché non sono considerati parte del rotativo dal punto di vista di Android. In genere vengono gestiti come i pulsanti Indietro e Home, ma con codici a tasti diversi. Ad esempio, KEYCODE_CALL o KEYCODE_MUSIC.

Configurazione build

La navigazione con il controllo rotatorio è fornita da un servizio di accessibilità chiamato RotaryService. Per includere questo servizio nell'immagine di sistema del dispositivo, aggiungi la seguente riga al makefile:

PRODUCT_PACKAGES += CarRotaryController

Ti consigliamo inoltre di includere i seguenti pacchetti nelle build di debug:

  • RotaryPlayground Un'app di riferimento per i dispositivi con rotazione (vedi RotaryPlayground).
  • RotaryIME Un IME rotatorio di prova (vedi Editor di metodi di input).
  • CarRotaryImeRRO L'overlay per RotaryIME.

Il servizio rotativo viene attivato automaticamente all'avvio del dispositivo e quando si verifica un cambio di utente. In questo modo, l'utente può utilizzare il controllo rotativo durante la configurazione.

Se utilizzi la stessa build per le auto con e senza un controller rotativo, aggiungi CarRotaryController come mostrato sopra in modo che il codice necessario sia incluso nella build. Per impedire l'attivazione del servizio di rotazione sulle auto non rotanti, crea un RRO statico per sovrapporre la risorsa stringa rotaryService in packages/services/Car/service con una stringa vuota. Utilizzerai la stessa build, ma avrai configurazioni dei prodotti separate per i dispositivi rotanti e non rotanti. Solo quest'ultimo include l'overlay.

Personalizzazione

Gli OEM possono personalizzare la logica di ricerca dell'attenzione, l'evidenziazione dell'attenzione e alcuni elementi aggiuntivi tramite gli overlay delle risorse nelle seguenti posizioni:

  • car-ui-library si trova in packages/apps/Car/libs/car-ui-lib
  • RotaryService si trova in packages/apps/Car/RotaryController
  • Core si trova in frameworks/base/core

Cronologia dei solleciti

L'OEM può configurare se attivare o meno ciascuno dei due tipi di cronologia dei solleciti e, in caso affermativo, le dimensioni della cache e il criterio di scadenza. Tutto questo viene fatto sostituendo varie risorse della libreria UI dell'auto.

Cache della cronologia di Focus

(Android 11 QPR3, Android 11 Car, Android 12)
Questa cache per FocusArea memorizza la visualizzazione attivata più di recente all'interno delFocusArea in modo che possa essere attivata quando si torna al FocusArea. Questa cache può essere configurata sovrapponendo le seguenti risorse della libreria UI dell'auto:

  • car_ui_focus_history_cache_type:
    1. La cache è disattivata.
    2. La cache scadrà dopo un po' di tempo (vedi di seguito).
    3. La cache non scade mai.
  • car_ui_focus_history_expiration_period_ms: il numero di millisecondi prima della scadenza della cache se il tipo di cache è impostato su due (2) (vedi sopra).

Cache della cronologia di FocusArea

(Android 11 QPR3, Android 11 Car, Android 12)
Questa cache memorizza una cronologia di spostamenti in modo che, spingendo nella direzione opposta, il focus possa tornare allo stesso FocusArea. Questa cache può essere configurata sovrapponendo le seguenti risorse car-ui-library:

  • car_ui_focus_area_history_cache_type:
    1. La cache è disattivata.
    2. La cache scade dopo un po' di tempo (vedi di seguito).
    3. La cache non scade mai.
  • car_ui_focus_area_history_expiration_period_ms: il numero di millisecondi prima della scadenza della cache se il tipo di cache è impostato su 2 (vedi sopra).
  • car_ui_clear_focus_area_history_when_rotating: indica se annullare la cache quando l'utente ruota il controller.

Rotazione

(Android 11 QPR3, Android 11 Car, Android 12)
L'OEM può sostituire due risorse intere in RotaryService per specificare se è presente un'accelerazione, ad esempio l'accelerazione del mouse, per la rotazione:

  • rotation_acceleration_3x_ms: intervallo di tempo (in millisecondi) utilizzato per decidere se Google deve accelerare la rotazione del controller per un dente di rotazione. Se l'intervallo tra questo dente e il dente di rotazione precedente è inferiore a questo valore, verrà considerato come tre denti di rotazione. Imposta questo valore su 2147483647 per disattivare l'accelerazione 3 volte.
  • rotation_acceleration_2x_ms: simile a rotation_acceleration_3x_ms. Utilizzato per un'accelerazione 2 volte superiore. Imposta questo valore su 2147483647 per disattivare l'accelerazione 2x.

L'accelerazione funziona al meglio quando sono presenti timestamp individuali per ogni scatto di rotazione, come richiesto dal VHAL. Se non sono disponibili, RotaryService presume che i detents di rotazione siano equidistanti.

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

Evidenziazione dell'elemento attivo

L'OEM può eseguire l'override dell'evidenziazione dell'elemento in primo piano predefinita nel framework Android e di diverse risorse di evidenziazione dell'elemento in primo piano nella libreria car-ui.

Evidenziazione dell'elemento attivo predefinita

Il framework Android fornisce un'evidenziazione dell'elemento in primo piano predefinita tramite l'attributoselectableItemBackground. In Theme.DeviceDefault, questo attributo fa riferimento a item_background.xml in Core. L'OEM può sovrapporre item_background.xml per modificare l'elemento Drawable di evidenziazione della messa a fuoco predefinito.

In genere, questo elemento drawable deve essere un StateListDrawable, che regola lo sfondo in base a diverse combinazioni di stati, tra cui android:state_focused e android:state_pressed. Quando l'utente utilizza il controllo rotativo per mettere in primo piano una visualizzazione, android:state_focused sarà true, maandroid:state_pressed sarà false. Se l'utente preme il pulsante centrale sul controller rotativo, sia android:state_focused sia android:state_pressed saranno true finché l'utente tiene premuto il pulsante. Quando l'utente rilascia il pulsante, rimane solo android:state_focusedtrue.

car-ui-library utilizza un tema derivato da Theme.DeviceDefault. Di conseguenza, questo overlay interessa le app che utilizzano questa libreria e le app che utilizzano qualsiasi tema derivato da Theme.DeviceDefault. Non influirà sulle app che utilizzano un tema non correlato, come Theme.Material.

Mettere in evidenza le risorse in car-ui-library

L'OEM può eseguire l'override di diverse risorse della libreria UI dell'auto per controllare l'aspetto dell'evidenziazione della funzionalità di messa a fuoco nelle visualizzazioni con un'evidenziazione della funzionalità di messa a fuoco non rettangolare (ad esempio rotonda o a forma di pillola) e nelle app che utilizzano un tema non derivato da Theme.DeviceDefault. Queste risorse devono essere sovrapposte in modo che l'evidenziazione dell'elemento attivo sia coerente con l'elemento drawable dell'evidenziazione dell'elemento attivo predefinita.

(Android 11 QPR3, Android 11 Car, Android 12)
Le seguenti risorse vengono utilizzate per indicare quando una visualizzazione è attiva, ma non è premuta:

  • car_ui_rotary_focus_fill_color: colore di riempimento.
  • car_ui_rotary_focus_stroke_color: colore del contorno.
  • car_ui_rotary_focus_stroke_width: spessore del contorno.

(Android 11 QPR3, Android 11 Car, Android 12)
Le seguenti risorse vengono utilizzate per indicare quando una visualizzazione è attivata e premuta:

  • car_ui_rotary_focus_pressed_fill_color: colore di riempimento.
  • car_ui_rotary_focus_pressed_stroke_color: colore del contorno.
  • car_ui_rotary_focus_pressed_stroke_width: spessore del contorno.

A volte a un pulsante viene assegnato un colore di sfondo a tinta unita per attirare l'attenzione dell'utente, come nell'esempio mostrato. Di conseguenza, l'evidenziazione della messa a fuoco potrebbe essere difficile da vedere.

Pulsante con sfondo a tinta unita
Figura 2. Pulsante con sfondo a tinta unita

In questo caso, lo sviluppatore può specificare un'evidenziazione personalizzata utilizzando i colori secondari:
  • (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

Qualsiasi colore può essere trasparente e una delle dimensioni può essere pari a zero se, ad esempio, vuoi solo un riempimento o solo un contorno.

Evidenziazione dell'area di messa a fuoco

(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea può disegnare due tipi di evidenziazione quando uno dei suoi discendenti è attivo. Se vuoi, puoi utilizzare entrambe le opzioni contemporaneamente. Questa funzionalità è disabilitata per impostazione predefinita in AOSP, ma può essere attivata sostituendo le risorse della libreria UI dell'auto:

  • car_ui_enable_focus_area_foreground_highlight: disegna un'evidenziazione sopraFocusArea e i suoi discendenti. In AOSP, questo drawable è un contorno attorno al FocusArea. Gli OEM possono eseguire l'override del drawable car_ui_focus_area_foreground_highlight.
  • car_ui_enable_focus_area_background_highlight: disegna un'evidenziazione sopra FocusArea, ma dietro i suoi discendenti. In AOSP, questo drawable è un riempimento a tinta unita. Gli OEM possono eseguire l'override del disegno car_ui_focus_area_background_highlight.

Editor di metodi di immissione

Gli Input Method Editor (IME) sono metodi di immissione. Ad esempio, una tastiera sullo schermo.

(Android 11 QPR3, Android 11 Car, Android 12)
L'OEM deve sovrapporre la risorsa stringa default_touch_input_method in RotaryService per specificare il ComponentName dell'IME basato su tocco. Ad esempio, se l'OEM utilizza l'IME fornito con Android Automotive, deve specificare com.google.android.apps.automotive.inputmethod/.InputMethodService.

(Android 11 QPR3, Android 11 Car, Android 12)
Se l'OEM ha creato un'IME specificamente per il selettore rotativo, deve specificarne il ComponentName nella risorsa rotary_input_method. Se questa risorsa è sovrapposta, l'IME specificato viene utilizzato ogni volta che l'utente interagisce con l'unità principale tramite il pulsante di spostamento, di rotazione e di centratura del controller rotativo. Quando l'utente tocca lo schermo, verrà utilizzato l'IME precedente. Il pulsante Indietro (e gli altri pulsanti del controller rotativo) non influiscono sulla selezione dell'IME. Se questa risorsa non è sovrapposta, non avviene il passaggio dall'IME. Carboard non supporta l'input rotatorio, pertanto l'utente non può inserire il testo tramite il controller rotatorio se l'OEM non ha fornito un IME rotatorio.

RotaryIME è un IME rotatorio di prova. Sebbene sia di base, è sufficiente per provare il passaggio automatico all'IME descritto sopra. Il codice sorgente di RotaryIME è disponibile in packages/apps/Car/tests/RotaryIME/.

Suggerimenti sullo schermo spento

Per impostazione predefinita, quando l'utente cerca di spostarsi dal bordo dello schermo, non succede nulla. L'OEM può configurare cosa deve accadere per ciascuna delle quattro direzioni specificando qualsiasi combinazione di:

  1. Un'azione globale definita da AccessibilityService. Ad esempio, GLOBAL_ACTION_BACK.
  2. Un codice chiave, ad esempio KEYCODE_BACK.
  3. Un'intenzione di avviare un'attività rappresentata come URL.

(Android 11 QPR3, Android 11 Car, Android 12)
Queste vengono specificate sovrapponendo le seguenti risorse array in RotaryService:

  • off_screen_nudge_global_actions: array di azioni globali da eseguire quando l'utente spinge verso l'alto, verso il basso, verso sinistra o verso destra dal bordo dello schermo. Non viene eseguita alcuna azione globale se l'elemento pertinente di questo array è -1.
  • off_screen_nudge_key_codes: array di codici chiave di eventi di clic da iniettare quando l'utente spinge verso l'alto, verso il basso, verso sinistra o verso destra dal bordo dello schermo. Non vengono inseriti eventi se l'elemento pertinente di questo array è 0 (KEYCODE_UNKNOWN).
  • off_screen_nudge_intents: array di intent per avviare un'attività quando l'utente spinge verso l'alto, verso il basso, verso sinistra o verso destra dal bordo dello schermo. Nessuna attività viene avviata se l'elemento pertinente di questo array è vuoto.

Altre configurazioni

Dovresti sovrapporre le seguenti risorse RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    config_showHeadsUpNotificationOnBottom: valore booleano per indicare se le notifiche in primo piano devono essere visualizzate in basso anziché in alto. Deve avere lo stesso valore della risorsa booleana config_showHeadsUpNotificationOnBottom in frameworks/base/packages/CarSystemUI/res/values/config.xml
  • (Android 11 QPR3, Android 11 Car, Android 12)
    notification_headsup_card_margin_horizontal: margine sinistro e destro per la finestra di notifica in primo piano. Deve avere lo stesso valore della risorsa dimen notification_headsup_card_margin_horizontal in packages/apps/Car/Notification/res/values/dimens.xml
  • (Android 12)
    excluded_application_overlay_window_titles: un array di titoli di finestre che non devono essere considerate finestre in overlay. Devono essere inclusi i titoli delle finestre dell'app che rappresentano TaskViews o TaskDisplayAreas. Per impostazione predefinita, questo elenco contiene solo "Maps".

Puoi sovrapporre la seguente risorsa RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    long_press_ms: valore intero che indica quanti millisecondi deve essere tenuto premuto il pulsante centrale per attivare una pressione prolungata. Zero indica che deve essere utilizzato il tempo di attesa predefinito per la pressione prolungata del sistema. Questo è il valore predefinito.