Kullanıcı HAL mülkleri

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'sini etkinleştirme

Kullanıcı HAL mülkleri, android.car.user_hal_enabled sistem mülkünün true olarak ayarlanmasıyla 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

user_hal_enabled adresini adb shell getprop android.car.user_hal_enabled veya adb logcat CarServiceHelper *:s kullanarak da kontrol edebilirsiniz. Mülk 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'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)
Android sistemi, cihaz önyüklendiğinde veya RAM'de askıya alma (STR) işleminden devam ettirildiğinde sistemin hangi Android kullanıcısını başlatacağını belirlemek için bu özelliği çağırı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 (varsayılan olarak beş saniye) sonra yürütme işlemini gerçekleştirmektir. 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ı için uzaktan kumanda algılanırsa ECU, HAL özelliğini geçersiz kılar ve başlatma sırasında Android sistemi belirtilen kullanıcıda başlayacak şekilde geçiş yapar.

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'yi 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ı Bununla birlikte, araba koltuğu ayarları Android kullanıcısına bağlı olduğundan kullanıcı değişimi 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 çağrıdır (yani HAL, anahtarı engelleyemez). Yalnızca başlatma sırasında (ilk kullanıcı geçişinden sonra) veya CarUserManager.switchUser() yerine ActivityManager.switchUser() çağrısı yapan 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ı. Daha sonra bir biyometrik sensör ECU'su sürücüyü İbrahim olarak tanımladı. Bu nedenle Kullanıcı HAL'si, kullanıcıları değiştirmek için 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'ye ve araç alt sistemlerinin geri kalanına bir istek gönderir. ECU'lar yeni oluşturulan kullanıcı hakkında bilgilendirilir. Ardından 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 aramadır. HAL'den herhangi bir yanıt beklenmemektedir.

Ö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. 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ğı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 kullanarak üst düzey temsile sahiptir ancak kaldırma işleminin standart VehiclePropValue nesneleri olarak birleştirilmesi gerekir (aşağıdaki örneklere bakın). Geliştirme sürecini kolaylaştırmak için AOSP'de, User 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 bir 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 bir 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

Örnek istek

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 istek

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 ayarlayın (Kullanıcı 10 ile ilişkili tuş birimi)

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
}