Molte architetture automobilistiche attuali contengono diverse unità di controllo elettroniche (ECU) esterne al sistema di infotainment che controllano l'ergonomia, come il sedile le impostazioni e le regolazioni del mirroring. In base all'hardware e all'alimentazione attuali , molte ECU si accendono prima del sistema di infotainment basato su Android sia acceso. Queste ECU possono interfacciarsi con un sistema di infotainment basato su Android tramite VHAL (VHAL).
A partire da Android 11, Android Automotive OS (AAOS) ha introdotto un nuovo set di proprietà sulla VHAL per la creazione, il cambio, la rimozione e l'associazione accessori esterni per identificare gli utenti. Ad esempio, queste nuove proprietà consentono Un conducente per collegare un accessorio esterno, ad esempio un portachiavi, all'utente Android. Poi, quando il conducente si avvicina al veicolo, una ECU si attiva e rileva la chiave elettronica. Questa ECU indica all'HAL quale utente Android deve usare il sistema di infotainment. avviare un avvio, che riduce il tempo di attesa del conducente per il suo Android Utente da caricare.
Attiva l'HAL per utente
Le proprietà HAL dell'utente devono essere abilitate in modo esplicito verificando che il sistema
la proprietà android.car.user_hal_enabled
è impostata su true
.
Questa operazione può essere eseguita anche nel file car.mk
, in modo che non sia necessario
manualmente.) Verifica che user_hal_enabled=true
sia attivato
eseguendo il dump di UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Puoi anche controllare user_hal_enabled
utilizzando adb shell
getprop android.car.user_hal_enabled
o adb logcat
CarServiceHelper *:s
. Se la proprietà è disattivata, viene visualizzato un messaggio come
all'avvio di system_server
:
I CarServiceHelper: Not using User HAL
Per attivare manualmente user_hal_enabled
, imposta il valore
android.car.user_hal_enabled
proprietà di sistema e riavvia
system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
L'output logcat
viene visualizzato 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 il ciclo di vita dell'utente che consentono 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, che il sistema Android effettua una richiesta impostando un valore di proprietà e HAL risponde inviando un evento di modifica della proprietà.
Nota: se è supportato User HAL, tutti i seguenti requisiti devono essere implementate.
proprietà HAL | Descrizione |
---|---|
INITIAL_USER_INFO (LEGGI/SCRITTURA) |
Questa proprietà viene chiamata dal sistema Android per determinare quale
Utente che il sistema si avvia quando il dispositivo si avvia o riprende da
Sospendi alla RAM (STR). Quando viene chiamato, l'HAL deve rispondere con uno dei seguenti
queste opzioni:
Nota:se l'HAL non risponde, il comportamento predefinito è vengono eseguiti dopo un periodo di timeout (per impostazione predefinita cinque secondi), 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. Esempio: per impostazione predefinita, il sistema Android viene avviato negli ultimi Utente attivo all'avvio. Se viene rilevata una chiave elettronica di un altro utente, la ECU sostituisce la proprietà HAL e, durante l'avvio, il sistema Android passa in quell'utente specificato. |
SWITCH_USER (LEGGI/SCRITTURA) |
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 di utente. I tre flussi di lavoro sono:
Il flusso di lavoro moderno utilizza un approccio di commit in due fasi per garantire Il sistema Android e la ECU esterna sono sincronizzati. Quando Android avvia il passaggio:
L'HAL dovrebbe attendere fino a dopo il Esempio:mentre è in movimento, un conducente tenta di Cambia utente Android nella UI dell'infotainment. Tuttavia, poiché seggiolino auto impostazioni sono legate all'utente Android, il posto si sposta durante Cambio di utente. Pertanto, la ECU che controlla i sedili non conferma il passaggio, l'HAL risponde con un errore e l'utente Android non viene cambiato.
Il flusso di lavoro legacy è una chiamata unidirezionale inviata dopo il cambio di utente
(di conseguenza, l'HAL non può bloccare l'interruttore). Viene chiamata solo all'avvio (dopo
cambio utente iniziale) o per le app che chiamano
Esempio:se un'app utilizza
Da Il flusso di lavoro del veicolo proviene dall'HAL, non dal sistema Android:
Esempio: Bob ha usato il portachiavi di Alice per aprire l'auto.
e l'HAL ha risposto alla richiesta |
CREATE_USER (LEGGI/SCRITTURA) |
Questa proprietà viene chiamata dal sistema Android quando un nuovo utente Android viene
creato (utilizzando l'API CarUserManager.createUser() ).
L'HAL risponde con Esempio:un conducente tocca l'icona di un'interfaccia utente di infotainment per Creare un nuovo utente Android. Viene inviata una richiesta all'HAL e agli altri dei sottosistemi dei veicoli. Le centraline vengono informate dell'utente appena creato. Altro e le ECU associano il loro ID utente interno all'app ID utente. |
REMOVE_USER (solo SCRITTURA) |
Il sistema Android chiama questa proprietà dopo che un utente Android
rimosso (con il metodo CarUserManager.removeUser() ).
Si tratta di una chiamata unidirezionale: non è prevista alcuna risposta dall'HAL. Esempio: un conducente tocca per rimuovere un conducente esistente. Utente Android nella UI di infotainment. L'HAL viene informato e i sottosistemi e le ECU dei veicoli vengono informati della rimozione dell'utente in modo possono 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 di essi può essere implementato senza supportare User HAL.
Proprietà HAL | Descrizione |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LEGGI/SCRITTURA) |
Utilizza questa proprietà per associare qualsiasi utente Android a un identificazione
come un portachiavi o uno smartphone. Utilizza questa stessa proprietà per
Associazioni get o set .
Esempio:un conducente tocca l'icona di un'interfaccia utente di infotainment da associare.
Il portachiavi usato per aprire il veicolo ( |
Librerie helper
Tutti gli oggetti utilizzati nei messaggi di richiesta e risposta (ad esempio,
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 (vedi gli esempi di seguito). Per facilità
di sviluppo,
C++
la libreria helper viene fornita in AOSP per convertire automaticamente l'HAL dell'utente
structs
in un VehiclePropValue
(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 complessivo è lo stesso, come illustrato di seguito:
Figura 1. Flusso di lavoro delle proprietà HAL dell'utente
Esempio di richiesta di un 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 moderna per un flusso di lavoro
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-cambio di un flusso di lavoro moderno
Questa risposta solitamente si verifica quando il passaggio ad Android va a buon fine:
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 dopo il passaggio a un flusso di lavoro moderno
Questa risposta solitamente si verifica quando un cambio Android non va a buon fine:
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 del 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 solitamente si verifica quando il passaggio ad Android va a buon fine:
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) }
CREATE_USER
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) }
ASSOCIAZIONE_IDENTIFICAZIONE_UTENTE
Imposta esempio (chiave elettronica associata 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 }