Kullanıcı HAL özellikleri

Mevcut birçok araç mimarisi, bilgi-eğlence sisteminin dışında koltuk ayarları ve ayna ayarları gibi ergonomiyi kontrol eden birden fazla elektronik kontrol birimi (ECU) içerir. Mevcut donanım ve güç mimarilerine bağlı olarak birçok ECU, Android tabanlı bilgi-eğlence sistemi açılmadan önce açılır. Bu ECU'lar, araç donanım soyutlama katmanı (VHAL) üzerinden Android tabanlı bir bilgi-eğlence sistemiyle arayüz oluşturabilir.

Android 11'den itibaren Android Automotive OS (AAOS), kullanıcıları tanımlamak için harici aksesuarlar oluşturmak, değiştirmek, kaldırmak ve ilişkilendirmek amacıyla VHAL'de yeni bir özellik grubu kullanıma sundu. Örneğin, bu yeni özellikler sayesinde sürücüler, anahtar fob gibi harici bir aksesuarı Android kullanıcılarıyla eşleyebilir. Ardından, sürücü araca yaklaştığında bir ECU uyanır ve anahtar kumandayı algılar. Bu ECU, HAL'e bilgi-eğlence sisteminin hangi Android kullanıcısını başlatması gerektiğini belirtir. Bu sayede sürücü, Android kullanıcısının yüklenmesini beklemek için daha az zaman harcar.

Kullanıcı HAL'ini etkinleştirme

android.car.user_hal_enabled sistem özelliğinin true olarak ayarlanmasıyla User HAL özellikleri açıkça etkinleştirilmelidir. (Bunu car.mk dosyasında yapabilirsiniz. Böylece manuel olarak ayarlanması gerekmez.) UserHalService'yi dökerek user_hal_enabled=true'nin etkinleştirildiğinden emin olun:

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

adb shell getprop android.car.user_hal_enabled veya adb logcat CarServiceHelper *:s kullanarak da user_hal_enabled'ü kontrol edebilirsiniz. Mülk devre dışıysa system_server başladığında aşağıdaki gibi bir mesaj görüntülenir:

I CarServiceHelper: Not using User HAL

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

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

logcat çıkışı 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 mülklerde, Android sisteminin bir mülk değeri ayarlayarak istek gönderdiği ve HAL'in bir mülk değişikliği etkinliği yayınlayarak yanıt verdiği bir istek ve yanıt protokolü kullanılır.

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

HAL mülkü Açıklama
INITIAL_USER_INFO
(okuma/yazma)
Bu mülk, cihaz açıldığında veya RAM'de askıya alma (STR) durumundan devam ettiğ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 ayarlanan varsayılan davranış (ilk önyükleme ise son kullanılan kullanıcıya geçme veya yeni bir kullanıcı oluşturma).
  • Mevcut bir kullanıcıya geçin.
  • Yeni bir kullanıcı oluşturun (isteğe bağlı ad, işaretler, sistem yerel dili vb. özellikleriyle) ve bu yeni kullanıcıya geçin.

Not: HAL yanıt vermezse varsayılan davranış, bir zaman aşımı süresinden sonra (varsayılan olarak beş saniye) yürütmektir. Bu da önyüklemeyi geciktirir. HAL yanıt verirse ancak Android sistemi işlemi yürütemezse (ör. maksimum kullanıcı sayısına ulaşıldıysa) varsayılan davranış kullanılır.

Örnek: Android sistemi varsayılan olarak, önyükleme sırasında son etkin kullanıcıda başlar. Farklı bir kullanıcıya ait bir anahtar fob'u algılanırsa ECU, HAL mülkünü geçersiz kılar ve Android sistemi, başlatma sırasında belirtilen kullanıcıda başlatılacak şekilde geçer.

SWITCH_USER
(okuma/yazma)
Bu mülk, etkin ön plan Android kullanıcısı değiştirilirken çağrılır. Mülk, kullanıcı geçişi isteğinde bulunmak için Android sistemi veya HAL tarafından çağrılabilir. Üç iş akışı şunlardır:
  • Modern. Geçiş CarUserManager tarihinde başladı.
  • Eski. Geçiş ActivityManager tarihinde başladı.
  • Araç. HAL tarafından kullanıcı geçişi isteğinde bulunmak için çağrılır.

Modern iş akışı, Android sisteminin ve harici ECU'nun senkronize olmasını sağlamak için iki aşamalı 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'i kontrol edin.

    HAL, Android'in devam edip etmeyeceği bilgisini SUCCESS veya FAILURE ile yanıtlar.

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

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

HAL, ECU'ları senkronize etmek veya diğer HAL özelliklerini güncellemek için durumunu güncellemek üzere ANDROID_POST_SWITCH yanıtını beklemelidir.

Örnek: Sürücünün, hareket halindeyken bilgi-eğlence sistemi kullanıcı arayüzünde Android kullanıcılarını değiştirmeye çalışması Ancak araba koltuğu ayarları Android kullanıcısına bağlı olduğundan, kullanıcı geçişi sırasında koltuk hareket eder. Bu nedenle, koltukları kontrol eden ECU geçişi onaylamıyor, HAL bir hata yanıtı veriyor ve Android kullanıcısı geçiş yapmıyor.

Eski iş akışı, kullanıcı geçiş yaptıktan sonra gönderilen tek yönlü bir aramadır (bu nedenle HAL geçişi engelleyemez). Yalnızca önyüklemede (ilk kullanıcı geçişinden sonra) veya CarUserManager.switchUser() yerine ActivityManager.switchUser() ç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'ler bu kullanımı değiştirmelidir.

Örnek: Bir uygulama, kullanıcı değiştirmek için ActivityManager.switchUser() kullanıyorsa kullanıcı değişiminin gerçekleştiğini bildirmek için HAL'e tek yönlü bir çağrı gönderilir.

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

  1. HAL, kullanıcı değiştirme isteğinde bulunur.
  2. Sistem, Android kullanıcı geçişini tamamlar.
  3. Android, anahtarlama işleminin başarılı veya başarısız olduğunu belirtmek için HAL'e bir ANDROID_POST_SWITCH yanıt gönderir.

Örnek: Boran, arabayı açmak için Aslı'nın anahtar kumandası kullandı ve HAL, INITIAL_USER_INFO isteğini Aslı'nın kullanıcı kimliğiyle yanıtladı. Ardından, bir biyometrik sensör ECU sürücüyü Bob olarak tanımladı. Bu nedenle, kullanıcı HAL'i kullanıcı değiştirmek için bir SWITCH_USER isteği gönderdi.

CREATE_USER
(okuma/yazma)
Bu mülk, 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 ile yanıt verir. HAL, bir hatayla yanıt verirse Android sistemi kullanıcıyı kaldırır.

Örnek: Bir sürücü, yeni bir Android kullanıcısı oluşturmak için bilgi-eğlence kullanıcı arayüzü simgesine dokunur. Bu işlem, HAL'e ve aracın diğer alt sistemlerine bir istek gönderir. ECU'lar yeni oluşturulan kullanıcı hakkında bilgilendirilir. Diğer alt sistemler ve ECU'lar, dahili kullanıcı kimliklerini Android kullanıcı kimliğiyle ilişkilendirir.

REMOVE_USER
(yalnızca KAYDET)
Android sistemi, bir Android kullanıcısı kaldırıldığında (CarUserManager.removeUser() yöntemiyle) bu özelliği çağırır.

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

Örnek: Bir sürücü, bilgi-eğlence kullanıcı arayüzünde mevcut bir Android kullanıcısını kaldırmak için dokunuyor. HAL bilgilendirilir ve diğer araç alt sistemleri ile ECU'lar, kullanıcının kaldırıldığı konusunda bilgilendirilir. Böylece, dahili kullanıcı kimliklerini kaldırabilirler.

Ek özellikler

Aşağıdakiler, kullanıcı yaşam döngüsü durumlarıyla alakalı olmayan ek özelliklerdir. Her biri, kullanıcı HAL'ini desteklemeden uygulanabilir.

HAL mülkü Açıklama
USER_IDENTIFICATION_ASSOCIATION
(okuma/yazma)
Herhangi bir Android kullanıcısını bir kimlik mekanizmasıyla (ör. anahtar fob veya telefon) ilişkilendirmek için bu mülkü kullanın. get veya set ilişkilendirmeleri için de aynı mülkü kullanın.

Örnek: Bir sürücü, aracı açmak için kullanılan anahtar fobisini (KEY_123) mevcut etkin Android kullanıcısıyla (USER_11) ilişkilendirmek üzere bir bilgi-eğlence kullanıcı arayüzü simgesine dokunur.

Yardımcı kitaplıklar

İstek ve yanıt mesajlarında kullanılan tüm nesneler (UserInfo, InitialUserInfoRequest, InitialUSerInfoResponse vb.) C++ struct kullanılarak yüksek düzeyde temsil edilir ancak kaldırma işlemi, standart VehiclePropValue nesnelerine düzleştirilmelidir (aşağıdaki örneklere bakın). Geliştirme sürecini kolaylaştırmak için AOSP'de, kullanıcı HAL structs'yi VehiclePropValue'a (ve bunun tersini) otomatik olarak dönüştüren bir C++ yardımcı kitaplığı sağlanır.

Örnekler

INITIAL_USER_INFO

İstek örneği (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şturma)

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
}

SWITCH_USER

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

İş Akışı

Şekil 1. Kullanıcı HAL özellikleri iş 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
}

Geçiş sonrası modern iş akışı yanıtı örneği

Bu yanıt genellikle Android geçişi başarılı olduğunda gerçekleşir:

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

Geçiş sonrası modern iş akışı yanıtı

Bu yanıt genellikle Android geçişi 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
}

Geçiş sonrası eski iş akışı yanıtı

Bu yanıt genellikle Android geçişi başarılı olduğunda gerçekleşir:

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

CREATE_USER

İstek örneği

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

İstek örneği

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 ayarlama (10. kullanıcıyla ilişkilendirilmiş anahtar fob)

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
}