Guida all'integrazione per gli OEM

Questa pagina descrive come elaborare gli input rotativi in VHAL, configurare la build in modo da includere il servizio rotativo e come personalizzare l'esperienza rotativa in tutte le app. Per le app OEM preinstallate, ad esempio un launcher fornito dall'OEM, vedi Libreria UI per auto (car-ui-library).

VHAL

Un controller rotativo supporta le seguenti azioni:

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

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

Il VHAL deve gestire queste azioni:

Colpetto di gomito

Quando l'utente spinge il controller 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. Target di visualizzazione.

Quando l'utente rilascia il controller rotativo, VHAL deve utilizzare la stessa proprietà e lo stesso keycode con ACTION_UP. I suggerimenti in altre direzioni devono utilizzare i codici chiave corrispondenti.

Non esistono codici chiave per le diagonali, ma l'HAL del veicolo può combinare un evento orizzontale e verticale per produrre una diagonale se l'hardware la supporta. Ad esempio, spostando leggermente verso l'alto e a sinistra si dovrebbe 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 controller rotativo dovrebbe produrre:

  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_LEFT ACTION_UP
  • HW_KEY_INPUT KEYCODE_SYSTEM_NAVIGATION_UP ACTION_UP

L'utente potrebbe spingere il controller rotativo in direzione perpendicolare prima di rilasciarlo. Ad esempio, il seguente scenario:

Direzione perpendicolare
Figura 1. Direzione perpendicolare

In questo modo dovrebbe essere generata 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 ripetuti mentre il controller rotativo è tenuto in una direzione.

Ruota

Quando l'utente ruota il controller rotativo in senso orario di uno scatto, l'HAL deve utilizzare la proprietà HW_ROTARY_INPUT con il seguente int32Values per inviare un evento ad Android:

  1. ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION
  2. Un (1) arresto.
  3. Target di visualizzazione.

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

Una rotazione di un (1) scatto in senso antiorario deve generare lo stesso evento, ma con -1 per il numero di scatti.

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

Ad esempio, la seguente sequenza di rotazioni:

  • Al momento t0, l'utente ha ruotato un dentello in senso antiorario.
  • Al tempo t0 + 5 ns, l'utente ha ruotato un arresto in senso antiorario.
  • Al tempo t0 + 8 ns, l'utente ha ruotato un arresto in senso antiorario.

dovrebbe generare questo evento:

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

Pulsante centrale

Quando l'utente preme il pulsante centrale, l'HAL del veicolo 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. Target di visualizzazione.

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

Non generare eventi ripetuti quando il pulsante centrale è 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. Target di visualizzazione.

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

Non devono essere generati eventi ripetuti mentre il pulsante Centro è premuto.

pulsante Home

Gestisci 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, VHAL può gestirli come preferisce l'OEM, in quanto non sono considerati parte del controller rotativo dal punto di vista di Android. In genere vengono gestiti come i pulsanti Indietro e Home, ma con codici tasto diversi. Ad esempio, KEYCODE_CALL o KEYCODE_MUSIC.

Configurazione build

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

PRODUCT_PACKAGES += CarRotaryController

Potresti anche voler includere i seguenti pacchetti nelle build di debug:

  • RotaryPlayground Un'app di riferimento per l'input rotatorio (vedi RotaryPlayground).
  • RotaryIME Un IME rotatorio demo (vedi Input Method Editor).
  • 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 controller rotativo durante la configurazione.

Se utilizzi la stessa build per le auto con e senza controller rotativo, aggiungi CarRotaryController come mostrato sopra in modo che il codice necessario sia incluso nella build. Per impedire l'attivazione del servizio rotativo su auto non rotative, 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 di prodotto separate per i dispositivi rotativi e non rotativi. Solo quest'ultimo include l'overlay.

Personalizzazione

Gli OEM possono personalizzare la logica di ricerca della messa a fuoco, l'evidenziazione della messa a fuoco e alcuni elementi aggiuntivi tramite 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 Nudge

L'OEM può configurare se attivare o meno ciascuno dei due tipi di cronologia dei suggerimenti e, in caso affermativo, le dimensioni della cache e la policy di scadenza. Tutto questo viene fatto eseguendo l'override di varie risorse di car-ui-library.

Cache della cronologia della messa a fuoco

(Android 11 QPR3, Android 11 Car, Android 12)
Questa cache per FocusArea memorizza la visualizzazione più recente all'interno del FocusArea in modo che possa essere selezionata quando si torna al FocusArea. Questa cache può essere configurata sovrapponendo le seguenti risorse car-ui-library:

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

Cache della cronologia di FocusArea

(Android 11 QPR3, Android 11 Car, Android 12)
Questa cache memorizza una cronologia dei suggerimenti in modo che i suggerimenti nella direzione opposta possano riportare lo stato attivo sullo stesso FocusArea. Questa cache può essere configurata sovrapponendo le seguenti risorse della libreria car-ui-library:

  • car_ui_focus_area_history_cache_type:
    1. La cache è disattivata.
    2. La cache scade dopo un po' di tempo (vedi sotto).
    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 invalidare la cache quando l'utente ruota il controller.

Rotazione

(Android 11 QPR3, Android 11 Car, Android 12)
L'OEM può eseguire l'override di 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 arresto della rotazione. Se l'intervallo tra questa tacca e la tacca di rotazione precedente è inferiore a questo valore, verrà considerato come tre tacche di rotazione. Imposta questo valore su 2147483647 per disattivare l'accelerazione 3×.
  • rotation_acceleration_2x_ms: simile a rotation_acceleration_3x_ms. Utilizzato per l'accelerazione 2×. Imposta questo valore su 2147483647 per disattivare l'accelerazione 2x.

L'accelerazione funziona meglio quando sono presenti timestamp individuali per ogni tacca di rotazione, come richiesto dall'HAL del veicolo. Se non sono disponibili, RotaryService presuppone che i detent di rotazione siano equispaziati.

/**
     * 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 della messa a fuoco

L'OEM può eseguire l'override dell'evidenziazione della messa a fuoco predefinita nel framework Android e di diverse risorse di evidenziazione della messa a fuoco in car-ui-library.

Evidenziazione dello stato attivo predefinita

Il framework Android fornisce un'evidenziazione predefinita dello stato attivo tramite l'attributo selectableItemBackground. In Theme.DeviceDefault, questo attributo si riferisce a item_background.xml in Core. L'OEM può sovrapporre item_background.xml per modificare la risorsa disegnabile di evidenziazione della messa a fuoco predefinita.

Questo elemento disegnabile in genere 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 controller rotativo per mettere a fuoco una visualizzazione, android:state_focused sarà true, ma android:state_pressed sarà false. Se l'utente preme il pulsante centrale sul controller rotativo, sia android:state_focused che android:state_pressed saranno true mentre l'utente tiene premuto il pulsante. Quando l'utente rilascia il pulsante, rimane solo android:state_focused true.

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

Risorse di evidenziazione del focus in car-ui-library

L'OEM può eseguire l'override di diverse risorse della libreria car-ui per controllare l'aspetto dell'evidenziazione della messa a fuoco nelle visualizzazioni con un'evidenziazione della messa a fuoco non rettangolare (ad esempio rotonda o a forma di pillola) e nelle app che utilizzano un tema che non deriva da Theme.DeviceDefault. Queste risorse devono essere sovrapposte in modo che l'evidenziazione dello stato attivo sia coerente con la risorsa disegnabile dell'evidenziazione dello stato attivo predefinita.

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

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

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

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

A volte a un pulsante viene assegnato un colore di sfondo pieno per attirare l'attenzione dell'utente, come nell'esempio mostrato. Ciò potrebbe rendere difficile la visualizzazione dell'evidenziazione della messa a fuoco.

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

In questa situazione, lo sviluppatore può specificare un'evidenziazione personalizzata dello stato attivo 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

Uno qualsiasi dei colori può essere trasparente e una delle dimensioni può essere zero se, ad esempio, vuoi solo un riempimento o solo un contorno.

FocusArea highlight

(Android 11 QPR3, Android 11 Car, Android 12)
FocusArea può disegnare due tipi di evidenziazione quando uno dei suoi discendenti è selezionato. Se vuoi, puoi utilizzarli insieme. Questa funzionalità è disattivata per impostazione predefinita in AOSP, ma può essere attivata sostituendo le risorse della libreria car-ui:

  • car_ui_enable_focus_area_foreground_highlight: disegna un'evidenziazione sopra il FocusArea e i relativi elementi secondari. In AOSP, questa risorsa disegnabile è un contorno intorno a FocusArea. Gli OEM possono eseguire l'override della risorsa disegnabile 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, questa risorsa disegnabile è un riempimento solido. Gli OEM possono eseguire l'override del drawable car_ui_focus_area_background_highlight.

Input Method Editors

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 ComponentName dell'IME basato sul 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 specifico per il controllo rotativo, deve specificarne 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 tocco, la rotazione e il pulsante centrale del controller rotativo. Quando l'utente tocca lo schermo, viene utilizzato il metodo di input precedente. Il pulsante Indietro (e gli altri pulsanti sul controller rotativo) non hanno alcun effetto sulla selezione della IME. Se questa risorsa non viene sovrapposta, non si verifica alcun cambio di IME. Cardboard non supporta la rotazione, quindi l'utente non può inserire testo tramite il controller rotatorio se l'OEM non ha fornito un IME rotatorio.

RotaryIME è un IME rotativo demo. Sebbene di base, è sufficiente per provare il cambio automatico dell'IME descritto sopra. Il codice sorgente per RotaryIME è disponibile in packages/apps/Car/tests/RotaryIME/.

Solleciti fuori dallo schermo

Per impostazione predefinita, quando l'utente tenta di spostare il contenuto fuori dallo schermo, non succede nulla. L'OEM può configurare cosa deve accadere per ciascuna delle quattro direzioni specificando una 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 intent per avviare un'attività rappresentata come URL.

(Android 11 QPR3, Android 11 Car, Android 12)
Questi vengono specificati sovrapponendo le seguenti risorse di array in RotaryService:

  • off_screen_nudge_global_actions: Array di azioni globali da eseguire quando l'utente scorre verso l'alto, il basso, sinistra o destra oltre il bordo dello schermo. Nessuna azione globale viene eseguita se l'elemento pertinente di questo array è -1.
  • off_screen_nudge_key_codes: Array di codici chiave degli eventi di clic da inserire quando l'utente si sposta verso l'alto, il basso, sinistra o 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 sposta il dito verso l'alto, il basso, sinistra o destra dal bordo dello schermo. Nessuna attività viene avviata se l'elemento pertinente di questo array è vuoto.

Altre configurazioni

Devi sovrapporre le seguenti risorse RotaryService:

  • (Android 11 QPR3, Android 11 Car, Android 12)
    config_showHeadsUpNotificationOnBottom: valore booleano per indicare se le notifiche heads-up devono essere mostrate 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 heads-up. Deve avere lo stesso valore della risorsa notification_headsup_card_margin_horizontal dimen 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 di overlay. Devono essere inclusi i titoli delle finestre delle 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 rappresenta il numero di millisecondi per cui il pulsante centrale deve essere tenuto premuto per attivare una pressione prolungata. Zero indica che deve essere utilizzato il timeout di pressione prolungata predefinito del sistema. Questo è il valore predefinito.