Proprietà HAL dell'utente

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:
  • Il comportamento predefinito impostato da Android (passando all'ultimo utilizzo utente o creazione di un nuovo utente se questo è il primo avvio).
  • Passa a un utente esistente.
  • Creare un nuovo utente (con le proprietà facoltative di name, flag, system impostazioni internazionali e così via) e passare al nuovo utente.

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:
  • Moderno. Passaggio avviato da CarUserManager.
  • Precedente. Passaggio avviato da ActivityManager.
  • Veicolo. Chiamata dall'HAL per richiedere il cambio di utente.

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:

  1. Controlla l'HAL per determinare se è possibile cambiare utente.

    L'HAL risponde con SUCCESS o FAILURE, quindi Android sa se procedere o meno.

  2. Completa il passaggio Utente Android.

    Android invia una risposta ANDROID_POST_SWITCH al HAL per indicare l'esito positivo o negativo del passaggio.

L'HAL dovrebbe attendere fino a dopo il ANDROID_POST_SWITCH risposta per aggiornare il proprio stato in modo da sincronizzare le ECU o aggiornare un altro HAL proprietà.

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 ActivityManager.switchUser() anziché CarUserManager.switchUser(). Il riferimento Le app Settings e SystemUI utilizzano già l'app la seconda, ma se un OEM fornisce le proprie app Impostazioni per cambiare utente, Gli OEM devono modificare l'utilizzo.

Esempio:se un'app utilizza Da ActivityManager.switchUser() a cambiare utente, viene inviata una chiamata unidirezionale all'HAL per informare che che il passaggio sia stato eseguito.

Il flusso di lavoro del veicolo proviene dall'HAL, non dal sistema Android:

  1. L'HAL richiede il cambio di utente.
  2. Il sistema completa il passaggio utente Android.
  3. Android invia una risposta ANDROID_POST_SWITCH all'HAL per indicare passaggio completato correttamente o non riuscito.

Esempio: Bob ha usato il portachiavi di Alice per aprire l'auto. e l'HAL ha risposto alla richiesta INITIAL_USER_INFO con ID utente di Alice. Poi una ECU con sensore biometrico identificava il conducente come Bob, L'HAL dell'utente ha inviato una richiesta SWITCH_USER di cambiare utente.

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 SUCCESS o FAILURE. Se HAL risponde con un errore, il sistema Android rimuove l'utente.

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 (KEY_123) per l'attuale utente Android attivo (USER_11).

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:

Flusso di lavoro

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
}