Molte architetture di veicoli attuali contengono più unità di controllo elettroniche (ECU) al di fuori del sistema di infotainment che controllano l'ergonomia, come le impostazioni del sedile e le regolazioni degli specchietti. Basate sull'hardware e sulle architetture di alimentazione attuali, molte centraline si accendono prima che il sistema di infotainment basato su Android venga acceso. Queste centraline possono interfacciarsi con un sistema di infotainment basato su Android tramite il Vehicle Hardware Abstraction Layer (VHAL) .
A partire da Android 11, Android Automotive OS (AAOS) ha introdotto un nuovo set di proprietà sul VHAL per creare, cambiare, rimuovere e associare accessori esterni per identificare gli utenti. Ad esempio, queste nuove proprietà consentono a un conducente di accoppiare un accessorio esterno, come un portachiavi, al proprio utente Android. Quindi, quando il conducente si avvicina al veicolo, una ECU si riattiva e rileva il portachiavi. Questa ECU indica all'HAL quale utente Android l'infotainment deve avviare un avvio, il che riduce il tempo di attesa del conducente per il caricamento del proprio utente Android.
Abilita l'HAL utente
Le proprietà User HAL devono essere abilitate in modo esplicito assicurandosi che la proprietà di sistema android.car.user_hal_enabled
sia impostata su true
. (Questo può essere fatto anche nel file car.mk
, in modo che non sia necessario impostarlo manualmente.) Verifica che user_hal_enabled=true
sia abilitato scaricando UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Puoi anche controllare user_hal_enabled
usando adb logcat CarServiceHelper *:s
. Se la proprietà è disabilitata, all'avvio system_server
viene visualizzato un messaggio come il seguente:
I CarServiceHelper: Not using User HAL
Per abilitare manualmente user_hal_enabled
, impostare la proprietà di sistema android.car.user_hal_enabled
e riavviare system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
L'output logcat
appare come segue:
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
Proprietà HAL dell'utente
Proprietà del ciclo di vita dell'utente
Le seguenti proprietà forniscono le informazioni HAL per gli stati del ciclo di vita dell'utente, che abilitano la sincronizzazione del ciclo di vita dell'utente tra il sistema Android e una ECU esterna. Queste proprietà utilizzano un protocollo di richiesta e risposta, in cui il sistema Android effettua una richiesta impostando un valore di proprietà e l'HAL risponde emettendo un evento di modifica della proprietà.
Nota: quando l'HAL utente è supportato, è necessario implementare tutte le seguenti proprietà.
Proprietà HAL | Descrizione |
---|---|
INITIAL_USER_INFO (LEGGERE SCRIVERE) | Questa proprietà viene chiamata dal sistema Android per determinare quale utente Android verrà avviato dal sistema all'avvio o al ripristino del dispositivo da Suspend-to-RAM (STR). Quando viene chiamato, l'HAL deve rispondere con una di queste opzioni:
Nota: se l'HAL non risponde, il comportamento predefinito prevede l'esecuzione dopo un periodo di timeout (cinque (5) secondi per impostazione predefinita), che ritarda l'avvio. Se l'HAL risponde, ma il sistema Android non riesce a eseguire l'azione (ad esempio, se è stato raggiunto il numero massimo di Utenti), viene utilizzato il comportamento predefinito. Ad esempio, per impostazione predefinita, il sistema Android viene avviato nell'ultimo Utente attivo all'avvio. Se viene rilevato un telecomando per un utente diverso, la ECU sovrascrive la proprietà HAL e, durante l'avvio, il sistema Android passa all'avvio in quell'utente specificato. |
SWITCH_USER (LEGGERE SCRIVERE) | Questa proprietà viene chiamata quando si cambia l'utente Android in primo piano attivo. La proprietà può essere chiamata sia dal sistema Android che dall'HAL per richiedere un cambio utente. I tre flussi di lavoro sono:
Il flusso di lavoro moderno utilizza un approccio di commit in due fasi per garantire che il sistema Android e l'ECU esterna siano sincronizzati. Quando Android avvia il passaggio:
L'HAL dovrebbe attendere fino a dopo la risposta Ad esempio, mentre è in movimento, un conducente tenta di cambiare gli utenti Android nell'interfaccia utente di infotainment. Tuttavia, poiché le impostazioni del seggiolino per auto sono legate all'utente Android, il sedile si sposterà durante il passaggio dell'utente. Pertanto, l'ECU che controlla i sedili non conferma il passaggio, l'HAL risponde con un errore e l'utente Android non viene commutato. Il flusso di lavoro Legacy è una chiamata unidirezionale inviata dopo il passaggio dell'utente (quindi l'HAL non può bloccare il passaggio). Viene chiamato solo all'avvio (dopo il cambio utente iniziale) o per le app che chiamano Ad esempio, se un'app utilizza Il flusso di lavoro del veicolo ha origine dall'HAL, non dal sistema Android:
Ad esempio , Bob ha utilizzato il telecomando di Alice per aprire l'auto e l'HAL ha risposto alla richiesta |
CREATE_USER (LEGGERE SCRIVERE) | Questa proprietà viene chiamata dal sistema Android quando viene creato un nuovo utente Android (utilizzando l'API CarUserManager.createUser() ). L'HAL risponde con Ad esempio, un conducente tocca un'icona dell'interfaccia utente di infotainment per creare un nuovo utente Android. Questo invia una richiesta all'HAL e al resto dei sottosistemi del veicolo. Le ECU vengono informate dell'Utente appena creato. Altri sottosistemi ed ECU associano quindi il proprio ID utente interno all'ID utente Android. |
REMOVE_USER (SOLO SCRITTURA) | Il sistema Android chiama questa proprietà dopo la rimozione di un utente Android (con l'API CarUserManager.removeUser() ).Questa è una chiamata unidirezionale: non è prevista alcuna risposta dall'HAL. Ad esempio, un conducente tocca per rimuovere un utente Android esistente nell'interfaccia utente di infotainment. L'HAL viene informato e gli altri sottosistemi del veicolo e le ECU vengono informati della rimozione dell'utente in modo che possano rimuovere il proprio ID utente interno. |
Ulteriori proprietà
Le seguenti sono proprietà aggiuntive, non correlate agli stati del ciclo di vita dell'utente. Ciascuno può essere implementato senza supportare l'HAL utente.
Proprietà HAL | Descrizione |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LEGGERE SCRIVERE) | Utilizzare questa proprietà per associare qualsiasi Utente Android a un meccanismo di identificazione, ad esempio un telecomando o un telefono. Utilizzare questa stessa proprietà per get o set associazioni.Ad esempio, un guidatore tocca un'icona dell'interfaccia utente di infotainment per associare il telecomando utilizzato per aprire il veicolo (KEY_123) all'utente Android attualmente attivo (USER_11). |
Librerie di supporto
Tutti gli oggetti usati nei messaggi di richiesta e risposta (come UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
e così via) hanno una rappresentazione di alto livello usando C++ struct
, ma la rimozione deve essere VehiclePropValue
standard (vedere gli esempi seguenti). Per facilitare lo sviluppo, in AOSP viene fornita una libreria di supporto C++ per convertire automaticamente le strutture HAL VehiclePropValue
structs
e viceversa).
Esempi
INITIAL_USER_INFO
Esempio di richiesta (al primo avvio)
VehiclePropValue { // flattened from InitialUserInfoRequest prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID [1] = 1 // InitialUserInfoRequestType.FIRST_BOOT [2] = 0 // user id of current user [3] = 1 // flags of current user (SYSTEM) [4] = 1 // number of existing users [5] = 0 // existingUser[0].id [6] = 1 // existingUser[0].flags }
Esempio di risposta (crea utente amministratore)
VehiclePropValue { // flattened from InitialUserInfoResponse prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID (must match request) [1] = 2 // InitialUserInfoResponseAction.CREATE [2] = -10000 // user id (not used on CREATE) [3] = 8 // user flags (ADMIN) prop.values.stringValue: "en-US||Car Owner" // User locale and User name }
CAMBIA UTENTE
Il nome effettivo delle classi e delle proprietà è leggermente diverso, ma il flusso di lavoro generale è lo stesso, come illustrato di seguito:
Figura 1. Flusso di lavoro delle proprietà HAL dell'utente
Esempio di richiesta di flusso di lavoro moderno
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896585 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID [1] = 2 // SwitchUserMessageType::ANDROID_SWITCH ("modern") [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Esempio di risposta del flusso di lavoro moderno
VehiclePropValue { // flattened from SwitchUserResponse prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // SwitchUserMessageType::VEHICLE_RESPONSE [2] = 1 // SwitchUserStatus::SUCCESS }
Esempio di risposta post-switch del flusso di lavoro moderno
Questa risposta si verifica in genere quando uno switch Android riesce:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Risposta post-cambio del flusso di lavoro moderno
Questa risposta si verifica in genere quando uno switch Android non riesce:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Esempio di richiesta di flusso di lavoro legacy
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 2 // Request ID [1] = 1 // SwitchUserMessageType::LEGACY_ANDROID_SWITCH [2,3] = 10,8 // target user id (10) and flags (ADMIN) [4,5] = 0,1 // current user id (0) and flags (SYSTEM) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Esempio di richiesta del flusso di lavoro del veicolo
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must be negative) [1] = 4 // SwitchUserMessageType::VEHICLE_REQUEST [2] = 11 // target user id }
Risposta post-cambio del flusso di lavoro legacy
Questa risposta si verifica in genere quando uno switch Android riesce:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must match from vehicle request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
CREARE UN UTENTE
Esempio di richiesta
VehiclePropValue { // flattened from CreateUserRequest prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,6 // Android id of the created user and flags (id=11, flags=GUEST, EPHEMERAL) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 3 // number of existing users (0, 10, 11) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [10,11] = 11,6 // newUser[2] (id=11, flags=GUEST,EPHEMERAL) }
Esempio di risposta
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
RIMUOVI_UTENTE
Esempio di richiesta
VehiclePropValue { // flattened from RemoveUserRequest prop: 299896586 // REMOVE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,0 // Android id of the removed user and flags (none in this case) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 2 // number of existing users (0, 10) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) }
USER_IDENTIFICATION_ASSOCIATION
Imposta esempio (portachiavi associato all'Utente 10)
VehiclePropValue { // flattened from UserIdentificationSetRequest prop: 299896587 // USER_IDENTIFICATION_ASSOCIATION prop.values.int32Values: [0] = 43 // Request ID [1,2] = 10,0 // Android id (10) and flags (none in this case) [3] = 1 // number of associations being set [4] = 1 // 1st type: UserIdentificationAssociationType::KEY_FOB [5] = 1 // 1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER }