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 jednostki ECU mogą współpracować 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 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 uruchomi system, gdy urządzenie zostanie uruchomione lub wznowione ze stanu wstrzymania do pamięci RAM (STR). Po wywołaniu warstwa HAL musi odpowiedzieć jedną z następujących 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 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. Na przykład domyślnie system Android uruchamia się po uruchomieniu 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 uruchamianie 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 przepływ pracy wykorzystuje dwufazowe podejście do zatwierdzania, aby zapewnić synchronizację systemu Android i zewnętrznego ECU. Gdy Android inicjuje przełączenie:
HAL powinna poczekać do odpowiedzi Na 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, fotelik przesunie się podczas zmiany użytkownika. Tym samym 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 Na przykład, jeśli aplikacja używa Przepływ pracy w pojeździe pochodzi z HAL, a nie z systemu Android:
Na przykład Bob użył pilota Alicji do otwarcia samochodu, a HAL odpowiedział na żądanie |
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 Na 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 systemu Android (za pomocą interfejsu API CarUserManager.removeUser() ).Jest to połączenie jednostronne — nie oczekuje się żadnej odpowiedzi ze strony HAL. Na przykład kierowca stuka, aby usunąć istniejącego użytkownika Androida 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.Na przykład kierowca klika ikonę interfejsu systemu informacyjno-rozrywkowego, aby powiązać brelok używany do otwierania pojazdu (KEY_123) z bieżącym aktywnym użytkownikiem Androida (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 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 (utwórz użytkownika administracyjnego)
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:
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 po pomyślnym przełączeniu 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] = 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) }
Reakcja po przełączeniu nowoczesnego 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 po pomyślnym przełączeniu systemu Android:
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 }