Benutzer-HAL-Eigenschaften

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 shell getprop android.car.user_hal_enabled oder 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:
  • Das von Android festgelegte Standardverhalten (Wechsel zum zuletzt verwendeten Benutzer oder Erstellen eines neuen Benutzers, wenn dies der erste Start ist).
  • Wechseln Sie zu einem bestehenden Benutzer.
  • Erstellen Sie einen neuen Benutzer (mit den optionalen Eigenschaften Name, Flags, Systemgebietsschema usw.) und wechseln Sie zu diesem neuen Benutzer.

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:
  • Modern. Switch gestartet von CarUserManager .
  • Erbe. Switch gestartet von ActivityManager .
  • Fahrzeug. Wird von der HAL aufgerufen, um einen Benutzerwechsel anzufordern.

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:

  1. Überprüfen Sie die HAL, um festzustellen, ob der Benutzer gewechselt werden kann.

    Die HAL antwortet mit SUCCESS oder FAILURE , sodass Android weiß, ob es fortfahren soll oder nicht.

  2. Schließen Sie den Android-Benutzerwechsel ab.

    Android sendet eine ANDROID_POST_SWITCH -Antwort an die HAL, um den Erfolg oder Misserfolg des Wechsels anzuzeigen.

Die HAL sollte bis nach der ANDROID_POST_SWITCH Antwort warten, um ihren Zustand zu aktualisieren, um ECUs zu synchronisieren oder andere HAL-Eigenschaften zu aktualisieren.

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 ActivityManager.switchUser() anstelle von CarUserManager.switchUser() . Die Referenz-Apps „ Settings “ und SystemUI verwenden bereits Letzteres, aber wenn ein OEM seine eigenen Settings-Apps bereitstellt, um Benutzer zu wechseln, sollten OEMs die Verwendung ändern.

Wenn eine App beispielsweise ActivityManager.switchUser() verwendet, um Benutzer zu wechseln, wird ein unidirektionaler Aufruf an die HAL gesendet, um darüber zu informieren, dass ein Benutzerwechsel stattgefunden hat.

Der Fahrzeug-Workflow stammt aus dem HAL, nicht aus dem Android-System:

  1. Die HAL fordert einen Benutzerwechsel an.
  2. Das System schließt den Android-Benutzerwechsel ab.
  3. Android sendet eine ANDROID_POST_SWITCH -Antwort an die HAL, um den Erfolg oder Misserfolg des Wechsels anzuzeigen.

Zum Beispiel benutzte Bob Alices Schlüsselanhänger, um das Auto zu öffnen, und der HAL antwortete auf die INITIAL_USER_INFO -Anfrage mit Alices Benutzer-ID. Als nächstes identifizierte ein ECU eines biometrischen Sensors den Fahrer als Bob, sodass der Benutzer HAL eine SWITCH_USER Anforderung zum Wechseln des Benutzers sendete.

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 SUCCESS oder FAILURE . Wenn die HAL mit einem Fehler antwortet, entfernt das Android-System den Benutzer.

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:

Arbeitsablauf

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
}