Wiele obecnych architektur pojazdów zawiera wiele elektronicznych jednostek sterujących (ECU) poza systemem informacyjno-rozrywkowym, które kontrolują ergonomię, takie jak ustawienia siedzeń i regulacja lusterek. W oparciu o aktualną architekturę sprzętu i zasilania, wiele ECU jest uruchamianych przed uruchomieniem systemu informacyjno-rozrywkowego opartego na Androidzie. Te ECU mogą łączyć się z systemem informacyjno-rozrywkowym opartym na Androidzie za pośrednictwem warstwy abstrakcji sprzętu pojazdu (VHAL) .
Począwszy od systemu Android 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 powiązanie zewnętrznego akcesorium, takiego jak brelok, ze swoim użytkownikiem Androida. Następnie, gdy kierowca zbliża się do pojazdu, ECU budzi się i wykrywa brelok. Ten ECU wskazuje HAL, który użytkownik systemu Android powinien uruchomić system informacyjno-rozrywkowy, co skraca czas oczekiwania sterownika na załadowanie użytkownika systemu Android.
Włącz warstwę HAL użytkownika
Właściwości warstwy HAL użytkownika 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
, aby nie trzeba było go ręcznie ustawiać). Sprawdź, czy user_hal_enabled=true
jest włączone, UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Możesz również sprawdzić user_hal_enabled
za pomocą adb logcat CarServiceHelper *:s
. Jeśli właściwość jest wyłączona, podczas uruchamiania system_server
wyświetlany jest 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 warstwy HAL użytkownika
Właściwości cyklu życia użytkownika
Poniższe właściwości zawierają informacje o warstwie HAL dla stanów cyklu życia użytkownika, które umożliwiają synchronizację cyklu życia użytkownika między systemem Android a zewnętrzną jednostką ECU. Te właściwości używają 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: W przypadku obsługi warstwy HAL użytkownika należy zaimplementować 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óry użytkownik systemu Android zostanie uruchomiony, gdy urządzenie zostanie uruchomione lub wznowione z trybu Suspend-to-RAM (STR). Po wywołaniu HAL musi odpowiedzieć jedną z tych opcji:
Uwaga: Jeśli warstwa HAL nie odpowiada, domyślnym zachowaniem jest wykonanie po upływie limitu czasu (domyślnie pięć (5) sekund), co opóźnia rozruch. Jeśli HAL odpowie, ale system Android nie wykona akcji (np. osiągnięto maksymalną liczbę Użytkowników), używane jest zachowanie domyślne. Na przykład domyślnie system Android po uruchomieniu uruchamia się od ostatniego aktywnego użytkownika. W przypadku wykrycia breloka dla innego Użytkownika, ECU nadpisuje właściwość HAL i podczas uruchamiania system Android przełącza się na uruchamianie u tego określonego Użytkownika. |
SWITCH_USER (ODCZYT/ZAPIS) | Ta właściwość jest wywoływana podczas przełączania aktywnego użytkownika Androida na pierwszym planie. Właściwość może być wywołana przez system Android lub przez warstwę HAL, aby zażądać zmiany użytkownika. Trzy przepływy pracy to:
Nowoczesny przepływ pracy wykorzystuje podejście zatwierdzania dwufazowego, aby zapewnić synchronizację systemu Android i zewnętrznej jednostki ECU. Gdy Android inicjuje zmianę:
HAL powinien poczekać do czasu odpowiedzi Na przykład podczas ruchu kierowca próbuje przełączyć użytkowników Androida w interfejsie systemu informacyjno-rozrywkowego. Ponieważ jednak ustawienia fotelika samochodowego są powiązane z użytkownikiem Androida, fotelik będzie się poruszał podczas zmiany użytkownika. Tym samym ECU sterujący fotelami nie potwierdza przełączenia, HAL odpowiada awarią, a Użytkownik Androida nie jest przełączany. Obieg pracy Legacy to jednokierunkowe połączenie wysyłane po przełączeniu użytkownika (więc warstwa HAL nie może zablokować przełącznika). Jest wywoływana tylko podczas rozruchu (po początkowym przełączeniu użytkownika) lub w przypadku aplikacji, które wywołują Na przykład, jeśli aplikacja używa Obieg pojazdu pochodzi z HAL, a nie z systemu Android:
Na przykład Bob użył breloczka Alicji do otwarcia samochodu, a HAL odpowiedział na żądanie |
CREATE_USER (ODCZYT/ZAPIS) | Ta właściwość jest wywoływana przez system Android podczas tworzenia nowego użytkownika Androida (przy użyciu interfejsu API CarUserManager.createUser() ). HAL odpowiada Na przykład kierowca klika ikonę interfejsu systemu informacyjno-rozrywkowego, aby utworzyć nowego użytkownika Androida. Powoduje to wysłanie żądania do HAL i pozostałych podsystemów pojazdu. ECU są informowane o nowo utworzonym Użytkowniku. Inne podsystemy i ECU następnie kojarzą swój wewnętrzny identyfikator użytkownika z identyfikatorem użytkownika Androida. |
REMOVE_USER (tylko ZAPISZ) | System Android wywołuje tę właściwość po usunięciu użytkownika Androida (za pomocą interfejsu API CarUserManager.removeUser() ).Jest to połączenie w jedną stronę — nie oczekuje się odpowiedzi z HAL. Na przykład kierowca stuka, aby usunąć istniejącego użytkownika Androida w interfejsie systemu informacyjno-rozrywkowego. HAL jest informowany, a inne podsystemy pojazdu i ECU są informowane o usunięciu użytkownika, aby mogły usunąć swój wewnętrzny identyfikator użytkownika. |
Dodatkowe właściwości
Poniżej przedstawiono dodatkowe właściwości, niezwiązane ze stanami cyklu życia użytkownika. Każdy może zostać zaimplementowany 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 Androida z mechanizmem identyfikacji, takim jak brelok lub telefon. Użyj tej samej właściwości, aby get lub set powiązania.Na przykład kierowca klika ikonę interfejsu systemu informacyjno-rozrywkowego, aby powiązać brelok użyty do otwarcia pojazdu (KEY_123) z bieżącym aktywnym użytkownikiem Androida (USER_11). |
Biblioteki pomocnicze
Wszystkie obiekty używane w komunikatach żądania i odpowiedzi (takie jak UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
itd.) mają reprezentację wysokiego poziomu przy użyciu C++ struct
, ale usuwanie musi być spłaszczone do standardowych obiektów VehiclePropValue
(zobacz przykłady poniżej). W celu ułatwienia programowania w AOSP dostępna jest biblioteka pomocnicza C++ , która automatycznie konwertuje structs
HAL użytkownika na wartość 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 (tworzenie użytkownika administratora)
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
Rzeczywista nazwa klas i właściwości różni się nieco, ale ogólny przepływ pracy jest taki sam, jak pokazano poniżej:
Rysunek 1. Przepływ pracy dotyczący właściwości warstwy HAL użytkownika
Przykład nowoczesnego 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 odpowiedzi na nowoczesny przepływ 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 odpowiedzi po przełączeniu nowoczesnego przepływu pracy
Ta odpowiedź zwykle pojawia się, gdy przełącznik systemu Android się powiedzie:
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, gdy przełącznik systemu Android ulegnie awarii:
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 }
Odpowiedź po przełączeniu starszego przepływu pracy
Ta odpowiedź zwykle pojawia się, gdy przełącznik systemu Android się powiedzie:
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
Przykład zapytania
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Ń_UŻYTKOWNIKA
Przykład zapytania
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 (pilot 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 }