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

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

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 shell getprop android.car.user_hal_enabled lub 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:
  • Domyślne zachowanie ustawione przez Androida (przełączenie na ostatnio używanego użytkownika lub utworzenie nowego użytkownika, jeśli jest to pierwsze uruchomienie).
  • Przełącz się 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ęć (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. Switch uruchomiony z CarUserManager .
  • Dziedzictwo. Switch uruchomiony z ActivityManager .
  • Pojazd. Wywoływany przez warstwę HAL w celu zażądania zmiany użytkownika.

Nowoczesny przepływ pracy wykorzystuje podejście zatwierdzania dwufazowego, aby zapewnić synchronizację systemu Android i zewnętrznej jednostki ECU. Gdy Android inicjuje zmianę:

  1. Sprawdź warstwę HAL, aby określić, czy użytkownik może zostać przełączony.

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

  2. Dokończ przełącznik użytkownika Androida.

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

HAL powinien poczekać do czasu odpowiedzi ANDROID_POST_SWITCH , aby zaktualizować swój stan w celu zsynchronizowania ECU lub zaktualizowania innych właściwości warstwy HAL.

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ą ActivityManager.switchUser() zamiast CarUserManager.switchUser() . Referencyjne aplikacje Settings i SystemUI już używają tych ostatnich, ale jeśli producent OEM udostępnia własne aplikacje Ustawienia do przełączania użytkowników, producenci OEM powinni zmienić użycie.

Na przykład, jeśli aplikacja używa ActivityManager.switchUser() do przełączania użytkowników, jednokierunkowe wywołanie jest wysyłane do warstwy HAL, aby poinformować, że nastąpiła zmiana użytkownika.

Obieg pojazdu pochodzi z HAL, a nie z systemu Android:

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

Na przykład Bob użył breloczka Alicji do otwarcia samochodu, a HAL odpowiedział na żądanie INITIAL_USER_INFO , podając identyfikator użytkownika Alicji. Następnie ECU czujnika biometrycznego zidentyfikował kierowcę jako Boba, więc użytkownik HAL wysłał żądanie SWITCH_USER , aby przełączyć użytkowników.

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 SUCCESS lub FAILURE . Jeśli HAL odpowie awarią, system Android usuwa Użytkownika.

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:

Przepływ pracy

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
}