Viele aktuelle Fahrzeugarchitekturen enthalten mehrere elektronische Steuereinheiten (ECUs) außerhalb des Infotainmentsystems, die die Ergonomie wie Sitzeinstellungen und Spiegeleinstellungen steuern. Basierend auf aktuellen Hardware- und Stromversorgungsarchitekturen werden viele ECUs hochgefahren, bevor das Android-basierte Infotainmentsystem hochgefahren wird. Diese ECUs können über den Vehicle Hardware Abstraction Layer (VHAL) mit einem Android-basierten Infotainmentsystem verbunden werden.
Ab Android 11 führte Android Automotive OS (AAOS) einen neuen Satz von Eigenschaften auf dem VHAL zum Erstellen, Wechseln, Entfernen und Zuordnen von externem Zubehör ein, um Benutzer zu identifizieren. Diese neuen Eigenschaften ermöglichen es einem Fahrer beispielsweise, ein externes Zubehör wie einen Schlüsselanhänger mit seinem Android- Benutzer zu koppeln. Wenn sich der Fahrer dann dem Fahrzeug nähert, wacht eine ECU auf und erkennt den Schlüsselanhänger. Diese ECU zeigt dem HAL an, welcher Android-Benutzer das Infotainment hochfahren soll, wodurch die Zeit verkürzt wird, die ein Fahrer auf das Laden seines Android-Benutzers wartet.
Aktivieren Sie die Benutzer-HAL
Die Benutzer-HAL-Eigenschaften müssen explizit aktiviert werden, indem sichergestellt wird, dass die Systemeigenschaft android.car.user_hal_enabled
auf true
gesetzt ist. (Dies kann auch in der Datei car.mk
, sodass es nicht manuell festgelegt werden muss.) Überprüfen Sie, user_hal_enabled=true
aktiviert ist, indem Sie den UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Sie können user_hal_enabled
auch mit überprüfen adb logcat CarServiceHelper *:s
. Wenn die Eigenschaft deaktiviert ist, wird beim Start von system_server
eine Meldung wie die folgende angezeigt:
I CarServiceHelper: Not using User HAL
Um user_hal_enabled
manuell zu aktivieren, legen Sie die android.car.user_hal_enabled
fest und starten system_server
neu:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
Die logcat
Ausgabe sieht wie folgt aus:
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
Benutzer-HAL-Eigenschaften
Eigenschaften des Benutzerlebenszyklus
Die folgenden Eigenschaften stellen die HAL-Informationen für Benutzerlebenszykluszustände bereit, die die Synchronisierung des Benutzerlebenszyklus zwischen dem Android-System und einem externen Steuergerät ermöglichen. Diese Eigenschaften verwenden ein Anfrage- und Antwortprotokoll, bei dem das Android-System eine Anfrage stellt, indem es einen Eigenschaftswert festlegt, und die HAL antwortet, indem sie ein Eigenschaftsänderungsereignis ausgibt.
Hinweis: Wenn Benutzer-HAL unterstützt wird, müssen alle folgenden Eigenschaften implementiert werden.
HAL-Eigenschaft | Beschreibung |
---|---|
INITIAL_USER_INFO (LESEN SCHREIBEN) | Diese Eigenschaft wird vom Android-System aufgerufen, um zu bestimmen, welchen Android-Benutzer das System startet, wenn das Gerät startet oder von Suspend-to-RAM (STR) fortgesetzt wird. Wenn der HAL aufgerufen wird, muss er mit einer der folgenden Optionen antworten:
Hinweis: Wenn die HAL nicht antwortet, wird sie standardmäßig nach einer Zeitüberschreitung (standardmäßig fünf (5) Sekunden) ausgeführt, was den Start verzögert. Wenn die HAL antwortet, das Android-System die Aktion jedoch nicht ausführt (z. B. wenn die maximale Anzahl von Benutzern erreicht wurde), wird das Standardverhalten verwendet. Beispielsweise startet das Android-System beim Booten standardmäßig im letzten aktiven Benutzer. Wenn ein Schlüsselanhänger für einen anderen Benutzer erkannt wird, setzt die ECU die HAL-Eigenschaft außer Kraft und während des Starts schaltet das Android-System um, um in diesem angegebenen Benutzer zu starten. |
SWITCH_USER (LESEN SCHREIBEN) | Diese Eigenschaft wird aufgerufen, wenn der aktive Android-Benutzer im Vordergrund gewechselt wird. Die Eigenschaft kann entweder vom Android-System oder vom HAL aufgerufen werden, um einen Benutzerwechsel anzufordern. Die drei Arbeitsabläufe sind:
Der moderne Workflow verwendet einen zweiphasigen Commit-Ansatz, um sicherzustellen, dass das Android-System und das externe Steuergerät synchronisiert sind. Wenn Android den Wechsel initiiert:
Die HAL sollte bis nach der Beispielsweise versucht ein Fahrer während der Fahrt, Android-Benutzer in der Infotainment-UI zu wechseln. Da die Autositzeinstellungen jedoch an den Android-Benutzer gebunden sind, bewegt sich der Sitz während des Benutzerwechsels. Somit bestätigt die ECU, die die Sitze steuert, den Wechsel nicht, die HAL antwortet mit einem Fehler und der Android-Benutzer wird nicht gewechselt. Der Legacy-Workflow ist ein unidirektionaler Anruf, der gesendet wird, nachdem der Benutzer gewechselt wurde (daher kann die HAL den Wechsel nicht blockieren). Es wird nur beim Booten (nach dem ersten Benutzerwechsel) oder für Apps aufgerufen, die Wenn eine App beispielsweise Der Fahrzeug-Workflow stammt aus dem HAL, nicht aus dem Android-System:
Zum Beispiel benutzte Bob Alices Schlüsselanhänger, um das Auto zu öffnen, und der HAL antwortete auf die |
CREATE_USER (LESEN SCHREIBEN) | Diese Eigenschaft wird vom Android-System aufgerufen, wenn ein neuer Android-Benutzer erstellt wird (mithilfe der CarUserManager.createUser() API). Die HAL antwortet mit Beispielsweise tippt ein Fahrer auf ein Infotainment-UI-Symbol, um einen neuen Android-Benutzer zu erstellen. Dies sendet eine Anforderung an die HAL und den Rest der Fahrzeugsubsysteme. ECUs werden über den neu erstellten Benutzer informiert. Andere Subsysteme und Steuergeräte verknüpfen dann ihre interne Benutzer-ID mit der Android-Benutzer-ID. |
REMOVE_USER (nur SCHREIBEN) | Das Android-System ruft diese Eigenschaft auf, nachdem ein Android-Benutzer entfernt wurde (mit der CarUserManager.removeUser() API).Dies ist ein unidirektionaler Anruf – es wird keine Antwort von der HAL erwartet. Beispielsweise tippt ein Fahrer, um einen bestehenden Android-Benutzer in der Infotainment-UI zu entfernen. Die HAL wird informiert und andere Fahrzeugsubsysteme und ECUs werden über die Entfernung des Benutzers informiert, damit sie ihre interne Benutzer-ID entfernen können. |
Zusätzliche Eigenschaften
Das Folgende sind zusätzliche Eigenschaften, die nichts mit den Benutzerlebenszykluszuständen zu tun haben. Jeder kann implementiert werden, ohne die Benutzer-HAL zu unterstützen.
HAL-Eigenschaft | Beschreibung |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LESEN SCHREIBEN) | Verwenden Sie diese Eigenschaft, um jeden Android-Benutzer mit einem Identifikationsmechanismus wie einem Schlüsselanhänger oder Telefon zu verknüpfen. Verwenden Sie dieselbe Eigenschaft, get Zuordnungen abzurufen oder set .Beispielsweise tippt ein Fahrer auf ein Infotainment-UI-Symbol, um den Schlüsselanhänger, der zum Öffnen des Fahrzeugs verwendet wird (KEY_123), mit dem derzeit aktiven Android-Benutzer (USER_11) zu verknüpfen. |
Hilfsbibliotheken
Alle in den Anforderungs- und Antwortnachrichten verwendeten Objekte (z. B. UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
usw.) haben eine High-Level-Darstellung unter Verwendung von C++ struct
, aber das Entfernen muss auf Standard- VehiclePropValue -Objekte VehiclePropValue
werden (siehe die Beispiele unten). Zur Vereinfachung der Entwicklung wird in structs
eine C++- Hilfsbibliothek bereitgestellt, um Benutzer-HAL-Strukturen automatisch in einen VehiclePropValue
(und umgekehrt) umzuwandeln.
Beispiele
INITIAL_USER_INFO
Anforderungsbeispiel (beim ersten Booten)
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 }
Antwortbeispiel (Admin-Benutzer erstellen)
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 }
BENUTZER WECHSELN
Der tatsächliche Name der Klassen und Eigenschaften unterscheidet sich geringfügig, aber der Gesamtablauf ist derselbe, wie unten dargestellt:
Abbildung 1. Workflow für Benutzer-HAL-Eigenschaften
Beispiel für eine moderne Workflow-Anfrage
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) }
Beispiel für eine moderne Workflow-Antwort
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 }
Beispiel für eine Post-Switch-Antwort eines modernen Workflows
Diese Antwort tritt normalerweise auf, wenn ein Android-Wechsel erfolgreich ist:
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) }
Post-Switch-Antwort moderner Arbeitsabläufe
Diese Antwort tritt normalerweise auf, wenn ein Android-Switch fehlschlägt:
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) }
Beispiel für Legacy-Workflow-Anforderungen
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) }
Beispiel für eine Fahrzeug-Workflow-Anfrage
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 }
Legacy-Workflow-Post-Switch-Antwort
Diese Antwort tritt normalerweise auf, wenn ein Android-Wechsel erfolgreich ist:
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
Beispiel anfordern
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) }
Antwortbeispiel
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
REMOVE_USER
Beispiel anfordern
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
Beispiel einstellen (Schlüsselanhänger mit Benutzer 10 verknüpft)
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 }