Benutzer-HAL-Eigenschaften

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:
  • Das von Android festgelegte Standardverhalten (Wechseln zum zuletzt verwendeten Benutzer oder Erstellen eines neuen Benutzers, wenn dies der erste Start ist).
  • Wechseln Sie zu einem vorhandenen 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, 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:
  • Modern. Der Wechsel wurde über CarUserManager gestartet.
  • Vermächtnis. Der Wechsel wurde über ActivityManager gestartet.
  • Fahrzeug. Wird von der HAL aufgerufen, um einen Benutzerwechsel anzufordern.

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:

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

    Der HAL antwortet mit SUCCESS oder FAILURE , sodass Android weiß, ob fortgefahren werden soll oder nicht.

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

    Android sendet eine ANDROID_POST_SWITCH Antwort an den HAL, um den erfolgreichen oder fehlgeschlagenen Wechsel anzuzeigen.

Der HAL sollte bis nach der ANDROID_POST_SWITCH -Antwort warten, um seinen Status zu aktualisieren, um Steuergeräte zu synchronisieren oder andere HAL-Eigenschaften zu aktualisieren.

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 ActivityManager.switchUser() anstelle von CarUserManager.switchUser() aufrufen. Die Referenz-Apps „ Settings und SystemUI verwenden Letzteres bereits. Wenn ein OEM jedoch seine eigenen Einstellungs-Apps zum Wechseln von Benutzern bereitstellt, sollten OEMs die Verwendung ändern.

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

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

  1. Der HAL fordert einen Benutzerwechsel an.
  2. Das System schließt den Android-Benutzerwechsel ab.
  3. Android sendet eine ANDROID_POST_SWITCH Antwort an den HAL, um den erfolgreichen oder fehlgeschlagenen Wechsel anzuzeigen.

Beispiel: Bob benutzte 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 biometrisches Sensor-ECU den Fahrer als Bob, sodass der Benutzer-HAL eine SWITCH_USER Anfrage zum Benutzerwechsel sendete.

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

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 ( KEY_123 ) dem aktuell aktiven Android-Benutzer ( USER_11 ) zuzuordnen.

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:

Arbeitsablauf

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
}