Molte attuali architetture di veicoli contengono più unità di controllo elettronico (ECU) esterne al sistema di infotainment che controllano l'ergonomia, come le impostazioni del sedile e la regolazione degli specchietti. Sulla base delle attuali architetture hardware e di alimentazione, molte ECU si accendono prima che venga acceso il sistema di infotainment basato su Android. Queste ECU possono interfacciarsi con un sistema di infotainment basato su Android tramite il Vehicle Hardware Abstraction Layer (VHAL) .
A partire da Android 11, il sistema operativo Android Automotive (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 associare un accessorio esterno, come un portachiavi, al proprio utente Android. Quindi, quando il conducente si avvicina al veicolo, una ECU si attiva e rileva la chiave. Questa ECU indica all'HAL quale utente Android l'infotainment dovrebbe avviare l'avvio, riducendo il tempo di attesa del conducente per il caricamento del proprio utente Android.
Abilita l'HAL utente
Le proprietà HAL utente devono essere abilitate esplicitamente 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.) Controlla 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
utilizzando adb logcat CarServiceHelper *:s
. Se la proprietà è disabilitata, all'avvio system_server
viene visualizzato un messaggio simile al seguente:
I CarServiceHelper: Not using User HAL
Per abilitare manualmente user_hal_enabled
, imposta la proprietà di sistema android.car.user_hal_enabled
e riavvia 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 un'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 è supportato l'HAL utente, è 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 riavvio 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 si avvia con l'ultimo Utente attivo all'avvio. Se viene rilevato un telecomando per un utente diverso, l'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 attivo in primo piano. La proprietà può essere chiamata dal sistema Android o dall'HAL per richiedere un cambio utente. I tre flussi di lavoro sono:
Il flusso di lavoro Modern 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 utente Android nell'interfaccia utente dell'infotainment. Tuttavia, poiché le impostazioni del seggiolino auto sono legate all'utente Android, il sedile si sposterà durante il cambio 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 cambio dell'utente (quindi l'HAL non può bloccare il cambio). 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 portachiavi 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. Ciò 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 loro ID utente interno all'ID utente Android. |
REMOVE_USER (Solo SCRITTURA) | Il sistema Android chiama questa proprietà dopo che un utente Android è stato rimosso (con l'API CarUserManager.removeUser() ).Si tratta di una chiamata unidirezionale: non è prevista alcuna risposta dall'HAL. Ad esempio, un conducente tocca per rimuovere un utente Android esistente nell'interfaccia utente dell'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. |
Proprietà aggiuntive
Di seguito sono riportate proprietà aggiuntive, non correlate agli stati del ciclo di vita dell'utente. Ciascuno può essere implementato senza supportare l'HAL dell'utente.
Proprietà HAL | Descrizione |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LEGGERE SCRIVERE) | Utilizza questa proprietà per associare qualsiasi utente Android a un meccanismo di identificazione, come un portachiavi o un telefono. Utilizzare questa stessa proprietà per get o set associazioni.Ad esempio, un conducente tocca un'icona dell'interfaccia utente di infotainment per associare la chiave utilizzata per aprire il veicolo (KEY_123) all'utente Android attualmente attivo (USER_11). |
Biblioteche di aiuto
Tutti gli oggetti utilizzati nei messaggi di richiesta e risposta (come UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
e così via) hanno una rappresentazione di alto livello utilizzando C++ struct
, ma la rimozione deve essere appiattita in oggetti VehiclePropValue
standard (vedere gli esempi seguenti). Per facilitare lo sviluppo, in AOSP viene fornita una libreria helper C++ per convertire automaticamente structs
HAL dell'utente in VehiclePropValue
(e viceversa).
Esempi
INITIAL_USER_INFO
Richiedi esempio (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à differisce leggermente ma il flusso di lavoro complessivo è lo stesso, come illustrato di seguito:
Figura 1. Flusso di lavoro delle proprietà HAL 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 un passaggio ad Android ha esito positivo:
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-switch del flusso di lavoro moderno
Questa risposta si verifica in genere quando un passaggio ad 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 di 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-passaggio del flusso di lavoro legacy
Questa risposta si verifica in genere quando un passaggio ad Android ha esito positivo:
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
Richiedi esempio
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
Richiedi esempio
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
Esempio di set (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 }