Kullanıcı HAL Özellikleri

Mevcut araç mimarilerinin çoğu, bilgi-eğlence sisteminin dışında, koltuk ayarları ve ayna ayarları gibi ergonomiyi kontrol eden birden fazla elektronik kontrol ünitesi (ECU) içerir. Mevcut donanım ve güç mimarilerine dayanarak, birçok ECU, Android tabanlı bilgi-eğlence sistemine güç verilmeden önce açılır. Bu ECU'lar , Araç Donanımı Soyutlama Katmanı (VHAL) aracılığıyla Android tabanlı bir bilgi-eğlence sistemi ile arayüz oluşturabilir.

Android 11'den başlayarak, Android Automotive OS (AAOS), Kullanıcıları tanımlamak için harici aksesuarların oluşturulması, değiştirilmesi, kaldırılması ve ilişkilendirilmesi için VHAL'de yeni bir dizi özellik sundu. Örneğin, bu yeni özellikler, bir sürücünün anahtarlık gibi harici bir aksesuarı Android Kullanıcısına eşleştirmesine olanak tanır. Ardından sürücü araca yaklaştığında ECU uyanır ve anahtarlığı algılar. Bu ECU, HAL'ye bilgi-eğlence sisteminin hangi Android Kullanıcısına önyükleme başlatması gerektiğini belirtir, bu da sürücünün Android Kullanıcısının yüklenmesini beklediği süreyi azaltır.

Kullanıcı HAL'sini Etkinleştir

Kullanıcı HAL özelliklerinin, android.car.user_hal_enabled sistem özelliğinin true olarak ayarlanması sağlanarak açıkça etkinleştirilmesi gerekir. (Bu aynı zamanda car.mk dosyasında da yapılabilir, böylece manuel olarak ayarlanmasına gerek kalmaz.) UserHalService dosyasının dökümünü alarak user_hal_enabled=true öğesinin etkinleştirilip etkinleştirilmediğini kontrol edin:

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

Ayrıca user_hal_enabled kullanarak da kontrol edebilirsiniz. adb kabuk getprop android.car.user_hal_enabled veya adb logcat CarServiceHelper *:s . Özellik devre dışı bırakılırsa system_server başlatıldığında aşağıdakine benzer bir mesaj görüntülenir:

I CarServiceHelper: Not using User HAL

user_hal_enabled manuel olarak etkinleştirmek için android.car.user_hal_enabled sistem özelliğini ayarlayın ve system_server yeniden başlatın:

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

logcat çıktısı aşağıdaki gibi görünür:

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

Kullanıcı HAL özellikleri

Kullanıcı yaşam döngüsü özellikleri

Aşağıdaki özellikler, Android sistemi ile harici bir ECU arasında Kullanıcı yaşam döngüsü senkronizasyonunu sağlayan Kullanıcı yaşam döngüsü durumları için HAL bilgilerini sağlar. Bu özellikler, Android sisteminin bir özellik değeri ayarlayarak istekte bulunduğu ve HAL'nin bir özellik değişikliği olayı düzenleyerek yanıt verdiği bir istek ve yanıt protokolünü kullanır.

Not: Kullanıcı HAL desteklendiğinde aşağıdaki özelliklerin tümü uygulanmalıdır.

HAL Özelliği Tanım
INITIAL_USER_INFO
(OKUMA YAZMA)
Bu özellik, cihaz RAM'e Askıya Alma'dan (STR) önyükleme yaptığında veya devam ettirildiğinde sistemin hangi Android Kullanıcısını başlatacağını belirlemek için Android sistemi tarafından çağrılır. HAL çağrıldığında aşağıdaki seçeneklerden biriyle yanıt vermelidir:
  • Android tarafından belirlenen varsayılan davranış (son kullanılan Kullanıcıya geçiş yapmak veya bu ilk önyükleme ise yeni bir Kullanıcı oluşturmak).
  • Mevcut bir Kullanıcıya geçin.
  • Yeni bir Kullanıcı oluşturun (isteğe bağlı ad, bayraklar, sistem yerel ayarı vb. özelliklerle) ve bu yeni Kullanıcıya geçin.

Not: HAL yanıt vermezse varsayılan davranış, önyüklemeyi geciktiren bir zaman aşımı süresinden sonra (varsayılan olarak beş (5) saniye) yürütülür. HAL yanıt verirse ancak Android sistemi eylemi yürütemezse (örneğin, maksimum Kullanıcı sayısına ulaşıldıysa), varsayılan davranış kullanılır.

Örneğin, varsayılan olarak Android sistemi, önyükleme sırasında son aktif Kullanıcıda başlar. Farklı bir Kullanıcı için bir anahtarlık algılanırsa ECU, HAL özelliğini geçersiz kılar ve başlatma sırasında Android sistemi, belirtilen Kullanıcıda başlatılacak şekilde geçiş yapar.

SWITCH_USER
(OKUMA YAZMA)
Bu özellik, etkin ön plan Android Kullanıcısı değiştirilirken çağrılır. Özellik, bir Kullanıcı anahtarı istemek için Android sistemi veya HAL tarafından çağrılabilir. Üç iş akışı şunlardır:
  • Modern. Geçiş CarUserManager başlatıldı.
  • Miras. Geçiş ActivityManager başlatıldı.
  • Araç. Kullanıcı değişikliği istemek için HAL tarafından çağrıldı.

Modern iş akışı, Android sistemi ile harici ECU'nun senkronize olmasını sağlamak için iki aşamalı bir taahhüt yaklaşımı kullanır. Android geçişi başlattığında:

  1. Kullanıcının değiştirilip değiştirilemeyeceğini belirlemek için HAL'yi kontrol edin.

    HAL, SUCCESS veya FAILURE ile yanıt verir, böylece Android devam edip etmeyeceğini bilir.

  2. Android Kullanıcı geçişini tamamlayın.

    Android, anahtarın başarılı veya başarısız olduğunu belirtmek için HAL'ye bir ANDROID_POST_SWITCH yanıtı gönderir.

HAL, ECU'ları senkronize etmek veya diğer HAL özelliklerini güncellemek amacıyla durumunu güncellemek için ANDROID_POST_SWITCH yanıtı sonrasına kadar beklemelidir.

Örneğin, hareket halindeyken bir sürücü bilgi-eğlence sistemi kullanıcı arayüzünde Android Kullanıcılarını değiştirmeye çalışır. Ancak araba koltuğu ayarları Android Kullanıcısına bağlı olduğundan, Kullanıcı değişimi sırasında koltuk hareket edecektir. Böylece koltukları kontrol eden ECU geçişi onaylamaz, HAL arızayla yanıt verir ve Android Kullanıcısı geçiş yapmaz.

Eski iş akışı, Kullanıcı değiştirildikten sonra gönderilen tek yönlü bir çağrıdır (böylece HAL, anahtarı engelleyemez). Yalnızca önyükleme sırasında (ilk kullanıcı geçişinden sonra) veya CarUserManager.switchUser() ActivityManager.switchUser() ) öğesini çağıran uygulamalar için çağrılır. Referans Settings ve SystemUI uygulamaları zaten ikincisini kullanıyor ancak bir OEM, Kullanıcıları değiştirmek için kendi Ayarlar uygulamalarını sağlıyorsa, OEM'lerin kullanımı değiştirmesi gerekir.

Örneğin, bir uygulama Kullanıcıları değiştirmek için ActivityManager.switchUser() kullanıyorsa, Kullanıcı değişikliğinin gerçekleştiğini bildirmek için HAL'ye tek yönlü bir çağrı gönderilir.

Araç iş akışı Android sisteminden değil HAL'den kaynaklanır:

  1. HAL bir Kullanıcı anahtarı ister.
  2. Sistem Android Kullanıcı geçişini tamamlar.
  3. Android, anahtarın başarılı veya başarısız olduğunu belirtmek için HAL'ye bir ANDROID_POST_SWITCH yanıtı gönderir.

Örneğin Bob, arabayı açmak için Alice'in anahtarlığını kullandı ve HAL, INITIAL_USER_INFO isteğine Alice'in Kullanıcı Kimliğiyle yanıt verdi. Daha sonra biyometrik sensör ECU'su sürücüyü Bob olarak tanımladı ve böylece Kullanıcı HAL, kullanıcıları değiştirmek için bir SWITCH_USER isteği gönderdi.

CREATE_USER
(OKUMA YAZMA)
Bu özellik, yeni bir Android Kullanıcısı oluşturulduğunda ( CarUserManager.createUser() API kullanılarak) Android sistemi tarafından çağrılır.

HAL, SUCCESS veya FAILURE olarak yanıt verir. HAL bir hatayla yanıt verirse Android sistemi Kullanıcıyı kaldırır.

Örneğin, bir sürücü yeni bir Android Kullanıcısı oluşturmak için bilgi-eğlence sistemi kullanıcı arayüzü simgesine dokunuyor. Bu, HAL'e ve araç alt sistemlerinin geri kalanına bir istek gönderir. ECU'lar yeni oluşturulan Kullanıcı hakkında bilgilendirilir. Diğer alt sistemler ve ECU'lar daha sonra dahili kullanıcı kimliklerini Android Kullanıcı Kimliğiyle ilişkilendirir.

REMOVE_USER
(Yalnızca YAZIN)
Android sistemi, bir Android Kullanıcısı kaldırıldıktan sonra ( CarUserManager.removeUser() API'si ile) bu özelliği çağırır.

Bu tek yönlü bir çağrıdır; HAL'den herhangi bir yanıt beklenmemektedir.

Örneğin, bir sürücü bilgi-eğlence sistemi kullanıcı arayüzünde mevcut bir Android Kullanıcısını kaldırmak için dokunur. HAL bilgilendirilir ve diğer araç alt sistemleri ve ECU'lar, dahili kullanıcı kimliklerini kaldırabilmeleri için Kullanıcının kaldırılması konusunda bilgilendirilir.

Ek özellikler

Aşağıda Kullanıcı yaşam döngüsü durumlarıyla ilgisi olmayan ek özellikler yer almaktadır. Her biri Kullanıcı HAL'sini desteklemeden uygulanabilir.

HAL Özelliği Tanım
USER_IDENTIFICATION_ASSOCIATION
(OKUMA YAZMA)
Herhangi bir Android Kullanıcısını anahtarlık veya telefon gibi bir tanımlama mekanizmasıyla ilişkilendirmek için bu özelliği kullanın. İlişkilendirmeleri get veya set için aynı özelliği kullanın.

Örneğin, bir sürücü, aracı açmak için kullanılan anahtarlığı (KEY_123) mevcut aktif Android Kullanıcısıyla (USER_11) ilişkilendirmek için bir bilgi-eğlence kullanıcı arayüzü simgesine dokunuyor.

Yardımcı kütüphaneler

İstek ve yanıt mesajlarında kullanılan tüm nesneler ( UserInfo , InitialUserInfoRequest , InitialUSerInfoResponse vb. gibi) C++ struct kullanılarak yüksek düzeyde bir temsile sahiptir, ancak kaldırma işlemi standart VehiclePropValue nesnelerine düzleştirilmelidir (aşağıdaki örneklere bakın). Geliştirme kolaylığı için, Kullanıcı HAL structs otomatik olarak bir VehiclePropValue (ve tersi) dönüştürmek için AOSP'de bir C++ yardımcı kitaplığı sağlanmıştır.

Örnekler

INITIAL_USER_INFO

Örnek isteyin (ilk açılışta)

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
}

Yanıt örneği (Yönetici Kullanıcı oluştur)

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
}

KULLANICI DEĞİŞTİR

Sınıfların ve özelliklerin gerçek adı biraz farklıdır ancak genel iş akışı aşağıda gösterildiği gibi aynıdır:

İş akışı

Şekil 1. Kullanıcı HAL Özellikleri İş Akışı

Modern iş akışı isteği örneği

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

Modern iş akışı yanıtı örneği

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
}

Modern iş akışı geçiş sonrası yanıt örneği

Bu yanıt genellikle bir Android geçişi başarılı olduğunda ortaya çıkar:

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

Modern iş akışı geçiş sonrası yanıt

Bu yanıt genellikle bir Android anahtarı başarısız olduğunda ortaya çıkar:

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

Eski iş akışı isteği örneği

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

Araç iş akışı isteği örneği

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
}

Eski iş akışı geçiş sonrası yanıtı

Bu yanıt genellikle bir Android geçişi başarılı olduğunda ortaya çıkar:

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

KULLANICI OLUŞTUR

Örnek isteyin

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

Yanıt örneği

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

REMOVE_USER

Örnek isteyin

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

Örnek ayarla (Kullanıcı 10 ile ilişkili anahtarlık)

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
}