Właściwości warstwy HAL użytkownika

Wiele obecnych konstrukcji pojazdów zawiera wiele elektronicznych jednostek sterujących (ECU) znajdujących się poza systemem informacyjno-rozrywkowym, które kontrolują ergonomię, np. ustawienia siedzeń i lusterek. W oparciu o obecną architekturę sprzętu i zasilania wiele ECU włącza się przed włączeniem systemu informacyjno-rozrywkowego opartego na systemie Android. Te ECU mogą łączyć się z systemem informacyjno-rozrywkowym opartym na systemie Android za pośrednictwem warstwy abstrakcji sprzętu pojazdu (VHAL) .

Począwszy od Androida 11, Android Automotive OS (AAOS) wprowadził nowy zestaw właściwości w VHAL do tworzenia, przełączania, usuwania i kojarzenia akcesoriów zewnętrznych w celu identyfikacji Użytkowników. Na przykład te nowe właściwości umożliwiają kierowcy sparowanie zewnętrznego akcesorium, takiego jak brelok, z użytkownikiem systemu Android. Następnie, gdy kierowca zbliża się do pojazdu, ECU budzi się i wykrywa brelok. Ten ECU wskazuje HAL, który użytkownik Androida powinien rozpocząć uruchamianie systemu informacyjno-rozrywkowego, co skraca czas oczekiwania kierowcy na załadowanie użytkownika Androida.

Włącz opcję HAL użytkownika

Właściwości User HAL muszą być jawnie włączone, upewniając się, że właściwość systemowa android.car.user_hal_enabled jest ustawiona na true . (Można to również zrobić w pliku car.mk , więc nie trzeba go ustawiać ręcznie.) Sprawdź, czy opcja user_hal_enabled=true jest włączona, zrzucając UserHalService :

$ adb shell dumpsys car_service --hal UserHalService|grep enabled
user_hal_enabled=true

Możesz także sprawdzić user_hal_enabled za pomocą adb shell getprop android.car.user_hal_enabled lub adb logcat CarServiceHelper *:s . Jeśli właściwość jest wyłączona, podczas uruchamiania system_server zostanie wyświetlony komunikat podobny do poniższego:

I CarServiceHelper: Not using User HAL

Aby ręcznie włączyć user_hal_enabled , ustaw właściwość systemową android.car.user_hal_enabled i zrestartuj system_server :

$ adb shell setprop android.car.user_hal_enabled true
$ adb shell stop && adb shell start

Dane wyjściowe logcat wyglądają następująco:

I CarServiceHelper: User HAL enabled with timeout of 5000ms
D CarServiceHelper: Got result from HAL: OK
I CarServiceHelper: User HAL returned DEFAULT behavior

Właściwości HAL użytkownika

Właściwości cyklu życia użytkownika

Poniższe właściwości dostarczają informacji HAL dla stanów cyklu życia użytkownika, które umożliwiają synchronizację cyklu życia użytkownika pomiędzy systemem Android a zewnętrznym ECU. Te właściwości korzystają z protokołu żądania i odpowiedzi, w którym system Android wysyła żądanie, ustawiając wartość właściwości, a warstwa HAL odpowiada, wydając zdarzenie zmiany właściwości.

Uwaga: jeśli obsługiwana jest warstwa HAL użytkownika, muszą zostać zaimplementowane wszystkie poniższe właściwości.

nieruchomość HAL Opis
INITIAL_USER_INFO
(ODCZYT/ZAPIS)
Ta właściwość jest wywoływana przez system Android w celu określenia, którego użytkownika systemu Android uruchamia system podczas uruchamiania urządzenia lub wznawiania działania ze stanu wstrzymania do pamięci RAM (STR). Po wywołaniu warstwa HAL musi odpowiedzieć jedną z następujących opcji:
  • Domyślne zachowanie ustawione przez Androida (przełączenie do ostatnio używanego Użytkownika lub utworzenie nowego Użytkownika, jeśli jest to pierwsze uruchomienie).
  • Przełącz na istniejącego użytkownika.
  • Utwórz nowego użytkownika (z opcjonalnymi właściwościami nazwy, flag, ustawień regionalnych systemu itd.) i przełącz się na tego nowego użytkownika.

Uwaga: Jeśli warstwa HAL nie odpowiada, domyślnym zachowaniem jest wykonanie po upływie limitu czasu (domyślnie pięć sekund), co opóźnia rozruch. Jeśli warstwa HAL odpowie, ale system Android nie wykona akcji (na przykład, jeśli została osiągnięta maksymalna liczba użytkowników), używane jest zachowanie domyślne.

Przykład: Domyślnie po uruchomieniu system Android uruchamia się z ostatnim aktywnym użytkownikiem. Jeśli zostanie wykryty brelok innego użytkownika, ECU zastępuje właściwość HAL i podczas uruchamiania system Android przełącza się na uruchomienie dla tego określonego użytkownika.

SWITCH_USER
(ODCZYT/ZAPIS)
Ta właściwość jest wywoływana podczas przełączania aktywnego użytkownika systemu Android na pierwszym planie. Właściwość może zostać wywołana przez system Android lub przez warstwę HAL w celu zażądania przełączenia użytkownika. Trzy przepływy pracy to:
  • Nowoczesny. Przełącznik uruchomiono z CarUserManager .
  • Dziedzictwo. Przełącznik uruchomiono z ActivityManager .
  • Pojazd. Wywoływane przez warstwę HAL w celu zażądania przełączenia użytkownika.

Nowoczesny przepływ pracy wykorzystuje dwufazowe podejście do zatwierdzania, aby zapewnić synchronizację systemu Android i zewnętrznego ECU. Gdy Android inicjuje przełączenie:

  1. Sprawdź warstwę HAL, aby określić, czy można przełączyć użytkownika.

    HAL odpowiada SUCCESS lub FAILURE , dzięki czemu Android wie, czy kontynuować, czy nie.

  2. Dokończ zmianę użytkownika Androida.

    Android wysyła odpowiedź ANDROID_POST_SWITCH do warstwy HAL, aby wskazać powodzenie lub niepowodzenie przełączenia.

HAL powinna poczekać do odpowiedzi ANDROID_POST_SWITCH , aby zaktualizować swój stan w celu synchronizacji ECU lub zaktualizować inne właściwości HAL.

Przykład: będąc w ruchu, kierowca próbuje przełączyć użytkowników Androida w interfejsie informacyjno-rozrywkowym. Ponieważ jednak ustawienia fotelika samochodowego są powiązane z użytkownikiem systemu Android, fotel przesuwa się podczas zmiany użytkownika. Zatem ECU sterujący siedzeniami nie potwierdza przełączenia, HAL odpowiada awarią, a użytkownik Androida nie zostaje przełączony.

Przepływ pracy Legacy to połączenie jednokierunkowe wysyłane po przełączeniu użytkownika (więc warstwa HAL nie może zablokować przełączenia). Jest wywoływana tylko podczas rozruchu (po początkowej zmianie użytkownika) lub w przypadku aplikacji wywołujących ActivityManager.switchUser() zamiast CarUserManager.switchUser() . Referencyjne aplikacje Settings i SystemUI już korzystają z tego ostatniego, ale jeśli producent OEM udostępnia własne aplikacje Ustawienia do zmiany użytkowników, producenci OEM powinni zmienić sposób użycia.

Przykład: Jeśli aplikacja używa ActivityManager.switchUser() do przełączania użytkowników, wówczas do warstwy HAL wysyłane jest wywołanie jednokierunkowe w celu poinformowania, że ​​nastąpiło przełączenie użytkownika.

Przepływ pracy w pojeździe pochodzi z HAL, a nie z systemu Android:

  1. HAL żąda zmiany użytkownika.
  2. System kończy zmianę użytkownika systemu Android.
  3. Android wysyła odpowiedź ANDROID_POST_SWITCH do warstwy HAL, aby wskazać powodzenie lub niepowodzenie przełączenia.

Przykład: Bob użył pilota Alicji do otwarcia samochodu, a HAL odpowiedział na żądanie INITIAL_USER_INFO , podając identyfikator użytkownika Alicji. Następnie czujnik biometryczny ECU zidentyfikował kierowcę jako Boba, więc użytkownik HAL wysłał żądanie SWITCH_USER w celu zmiany użytkowników.

CREATE_USER
(ODCZYT/ZAPIS)
Ta właściwość jest wywoływana przez system Android, gdy tworzony jest nowy użytkownik Androida (przy użyciu interfejsu API CarUserManager.createUser() ).

HAL odpowiada SUCCESS lub FAILURE . Jeżeli HAL zareaguje niepowodzeniem, system Android usuwa Użytkownika.

Przykład: kierowca dotyka ikony interfejsu informacyjno-rozrywkowego, aby utworzyć nowego użytkownika systemu Android. Spowoduje to wysłanie żądania do HAL i pozostałych podsystemów pojazdu. ECU są informowane o nowo utworzonym Użytkowniku. Inne podsystemy i ECU łączą następnie swój wewnętrzny identyfikator użytkownika z identyfikatorem użytkownika systemu Android.

REMOVE_USER
(tylko PISAJ)
System Android wywołuje tę właściwość po usunięciu użytkownika Androida (za pomocą metody CarUserManager.removeUser() ).

Jest to połączenie jednostronne — nie oczekuje się żadnej odpowiedzi ze strony HAL.

Przykład: kierowca klika, aby usunąć istniejącego użytkownika systemu Android w interfejsie informacyjno-rozrywkowym. HAL jest informowany, a inne podsystemy pojazdu i ECU są informowane o usunięciu użytkownika, dzięki czemu mogą usunąć swój wewnętrzny identyfikator użytkownika.

Dodatkowe właściwości

Poniżej znajdują się dodatkowe właściwości, niezwiązane ze stanami cyklu życia użytkownika. Każdy z nich można wdrożyć bez obsługi warstwy HAL użytkownika.

Nieruchomość HAL Opis
USER_IDENTIFICATION_ASSOCIATION
(ODCZYT/ZAPIS)
Użyj tej właściwości, aby powiązać dowolnego użytkownika systemu Android z mechanizmem identyfikacji, takim jak brelok lub telefon. Użyj tej samej właściwości, aby get lub set skojarzenia.

Przykład: kierowca dotyka ikony interfejsu systemu informacyjno-rozrywkowego, aby powiązać brelok używany do otwierania pojazdu ( KEY_123 ) z bieżącym aktywnym użytkownikiem systemu Android ( USER_11 ).

Biblioteki pomocnicze

Wszystkie obiekty używane w komunikatach żądań i odpowiedzi (takie jak UserInfo , InitialUserInfoRequest , InitialUSerInfoResponse itd.) mają reprezentację wysokiego poziomu przy użyciu struktury C++ struct , ale usunięcie musi zostać spłaszczone do standardowych obiektów VehiclePropValue (zobacz przykłady poniżej). Aby ułatwić programowanie, w AOSP dostępna jest biblioteka pomocnicza C++ , która automatycznie konwertuje structs HAL użytkownika na VehiclePropValue (i odwrotnie).

Przykłady

INITIAL_USER_INFO

Przykład żądania (przy pierwszym uruchomieniu)

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
}

Przykład odpowiedzi (utwórz użytkownika Admin)

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
}

ZMIEŃ UŻYTKOWNIKA

Rzeczywiste nazwy klas i właściwości różnią się nieco, ale ogólny przebieg pracy jest taki sam, jak pokazano poniżej:

Przepływ pracy

Rysunek 1. Przebieg pracy dotyczący właściwości HAL użytkownika

Przykład nowoczesnego żądania przepływu pracy

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)
}

Przykład nowoczesnej reakcji przepływu pracy

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
}

Przykład reakcji nowoczesnego przepływu pracy po przełączeniu

Ta odpowiedź zwykle występuje, gdy przełączenie systemu Android zakończy się pomyślnie:

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)
}

Nowoczesna reakcja po przełączeniu przepływu pracy

Ta odpowiedź zwykle występuje w przypadku awarii przełącznika systemu Android:

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)
}

Przykład żądania starszego przepływu pracy

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)
}

Przykład żądania przepływu pracy pojazdu

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
}

Reakcja po przełączeniu starszego przepływu pracy

Ta odpowiedź zwykle występuje, gdy przełączenie systemu Android zakończy się pomyślnie:

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)
}

STWÓRZ UŻYTKOWNIKA

Poproś o przykład

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)
}

Przykład odpowiedzi

VehiclePropValue { // flattened from CreateUserResponse
prop: 299896585 // CREATE_USER
prop.values.int32Values:
 [0] = 42        // Request ID (must match request)
 [1] = 3         // CreateUserStatus::SUCCESS
}

USUŃ_USERA

Poproś o przykład

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

Ustaw przykład (breloczek powiązany z użytkownikiem 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
}