Viele aktuelle Fahrzeugarchitekturen enthalten mehrere elektronische Steuergeräte (ECUs) außerhalb des Infotainmentsystems, die die Ergonomie steuern, beispielsweise Sitzeinstellungen und Spiegeleinstellungen. Basierend auf aktuellen Hardware- und Leistungsarchitekturen werden viele Steuergeräte hochgefahren, bevor das Android-basierte Infotainmentsystem hochgefahren wird. Diese Steuergeräte können über die 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 im VHAL zum Erstellen, Wechseln, Entfernen und Zuordnen externer Zubehörteile zur Identifizierung von Benutzern ein. Diese neuen Eigenschaften ermöglichen es einem Fahrer beispielsweise, ein externes Zubehörteil, beispielsweise einen Schlüsselanhänger, mit seinem Android-Benutzer zu koppeln . Wenn sich der Fahrer dann dem Fahrzeug nähert, aktiviert sich ein Steuergerät und erkennt den Schlüsselanhänger. Dieses Steuergerät zeigt dem HAL an, für welchen Android-Benutzer das Infotainment einen Startvorgang starten soll, was die Zeit verkürzt, die ein Treiber auf das Laden seines Android-Benutzers wartet.
Aktivieren Sie den 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
erfolgen, sodass es nicht manuell festgelegt werden muss.) Überprüfen Sie, ob user_hal_enabled=true
aktiviert ist, indem Sie den UserHalService
sichern:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Sie können user_hal_enabled
auch überprüfen, indem Sie adb shell getprop android.car.user_hal_enabled
oder adb logcat CarServiceHelper *:s
verwenden. Wenn die Eigenschaft deaktiviert ist, wird beim Start system_server
eine Meldung wie die folgende angezeigt:
I CarServiceHelper: Not using User HAL
Um user_hal_enabled
manuell zu aktivieren, legen Sie die Systemeigenschaft android.car.user_hal_enabled
fest und starten Sie 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 Anforderungs- und Antwortprotokoll, bei dem das Android-System eine Anforderung stellt, indem es einen Eigenschaftswert festlegt, und der HAL antwortet, indem er ein Eigenschaftsänderungsereignis ausgibt.
Hinweis: Wenn User 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) fortfährt. Beim Aufruf muss die HAL mit einer dieser Optionen antworten:
Hinweis: Wenn die HAL nicht antwortet, erfolgt die Ausführung standardmäßig nach einer Zeitüberschreitung (standardmäßig fünf Sekunden), wodurch der Start verzögert wird. Wenn der HAL zwar antwortet, das Android-System die Aktion jedoch nicht ausführt (z. B. wenn die maximale Anzahl von Benutzern erreicht wurde), wird das Standardverhalten verwendet. Beispiel: Standardmäßig startet das Android-System beim Booten mit dem letzten aktiven Benutzer. Wenn ein Schlüsselanhänger für einen anderen Benutzer erkannt wird, überschreibt das Steuergerät die HAL-Eigenschaft und beim Start wechselt das Android-System zum Start in diesem angegebenen Benutzer. |
SWITCH_USER (LESEN SCHREIBEN) | Diese Eigenschaft wird aufgerufen, wenn der aktive Vordergrund-Android-Benutzer gewechselt wird. Die Eigenschaft kann entweder vom Android-System oder von der HAL aufgerufen werden, um einen Benutzerwechsel anzufordern. Die drei Arbeitsabläufe sind:
Der Modern-Workflow verwendet einen zweiphasigen Commit-Ansatz, um sicherzustellen, dass das Android-System und das externe Steuergerät synchronisiert werden. Wenn Android den Wechsel einleitet:
Der HAL sollte bis nach der Beispiel: Während der Fahrt versucht ein Fahrer, den Android-Benutzer in der Infotainment-Benutzeroberfläche zu wechseln. Da die Autositzeinstellungen jedoch an den Android-Benutzer gebunden sind, bewegt sich der Sitz beim Benutzerwechsel. Daher bestätigt die ECU, die die Sitze steuert, den Wechsel nicht, der HAL antwortet mit einem Fehler und der Android-Benutzer wird nicht umgeschaltet. Der Legacy-Workflow ist ein unidirektionaler Anruf, der nach dem Wechsel des Benutzers gesendet wird (damit der HAL den Wechsel nicht blockieren kann). Es wird nur beim Booten (nach dem ersten Benutzerwechsel) oder für Apps aufgerufen, die Beispiel: Wenn eine App Der Fahrzeug-Workflow stammt aus dem HAL, nicht aus dem Android-System:
Beispiel: Bob benutzte 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). Der HAL antwortet mit Beispiel: Ein Fahrer tippt auf ein Infotainment-UI-Symbol, um einen neuen Android-Benutzer zu erstellen. Dadurch wird eine Anfrage an den HAL und die übrigen Fahrzeugsubsysteme gesendet. Steuergeräte werden über den neu angelegten 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 Methode CarUserManager.removeUser() ).Dies ist ein einseitiger Anruf – vom HAL wird keine Antwort erwartet. Beispiel: Ein Fahrer tippt auf, um einen vorhandenen Android-Benutzer in der Infotainment-Benutzeroberfläche zu entfernen. Der HAL wird informiert und andere Fahrzeugsubsysteme und Steuergeräte werden über die Benutzerentfernung informiert, damit sie ihre interne Benutzer-ID entfernen können. |
Zusätzliche Eigenschaften
Im Folgenden finden Sie zusätzliche Eigenschaften, die nichts mit den Benutzerlebenszyklusstatus zu tun haben. Jedes kann ohne Unterstützung des Benutzer-HAL implementiert werden.
HAL-Eigenschaft | Beschreibung |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LESEN SCHREIBEN) | Verwenden Sie diese Eigenschaft, um jeden Android-Benutzer einem Identifikationsmechanismus zuzuordnen, beispielsweise einem Schlüsselanhänger oder einem Telefon. Verwenden Sie dieselbe Eigenschaft, um Zuordnungen get oder set . Beispiel: Ein Fahrer tippt auf ein Infotainment-UI-Symbol, um den zum Öffnen des Fahrzeugs verwendeten Schlüsselanhänger ( |
Hilfsbibliotheken
Alle in den Anforderungs- und Antwortnachrichten verwendeten Objekte (z. B. UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
usw.) verfügen über eine Darstellung auf hoher Ebene mithilfe der C++- struct
, die Entfernung muss jedoch in standardmäßige VehiclePropValue
Objekte reduziert werden (siehe Beispiele unten). Zur Vereinfachung der Entwicklung wird in AOSP eine C++-Hilfsbibliothek bereitgestellt, um Benutzer-HAL- structs
automatisch in einen VehiclePropValue
(und umgekehrt) zu konvertieren.
Beispiele
INITIAL_USER_INFO
Anforderungsbeispiel (beim ersten Start)
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 (Administratorbenutzer 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 gesamte Arbeitsablauf ist derselbe, wie unten dargestellt:
Abbildung 1. Arbeitsablauf 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 Reaktion nach dem Wechsel eines modernen Workflows
Diese Reaktion 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) }
Moderne Workflow-Reaktion nach dem Wechsel
Diese Reaktion 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 eine Legacy-Workflow-Anfrage
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 }
Reaktion des alten Workflows nach dem Wechsel
Diese Reaktion 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 festlegen (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 }