تحتوي العديد من تصاميم المركبات الحالية على وحدات تحكّم إلكترونية متعددة (ECU) خارج نظام المعلومات والترفيه للتحكّم في وظائف سهولة الاستخدام، مثل إعدادات المقعد وتعديل المرايا. استنادًا إلى تصاميم الأجهزة والطاقة الحالية، يتم تشغيل العديد من وحدات التحكّم الإلكترونية قبل تشغيل نظام الترفيه والمعلومات المستنِد إلى Android. يمكن أن تتفاعل وحدات التحكّم الإلكترونية هذه مع نظام الترفيه والمعلومات المستنِد إلى Android من خلال طبقة تجريد أجهزة المركبات (VHAL).
بدءًا من الإصدار 11 من نظام التشغيل Android، قدّم نظام التشغيل Android Automotive (AAOS) مجموعة جديدة من السمات في VHAL لإنشاء الملحقات الخارجية بديلة واستخدامها وتبديلها وإزالتها وربطها لتحديد المستخدمين. على سبيل المثال، تتيح هذه السمات الجديدة للسائق إقران ملحق خارجي، مثل مفتاح السيارة، بمستخدم Android. بعد ذلك، عندما يقترب السائق من المركبة، يتم تنشيط وحدة التحكّم الإلكترونية (ECU) ورصد المفتاح اللاسلكي. يشير وحدة التحكّم في المحرك هذه إلى HAL بشأن مستخدم Android الذي يجب أن يبدأ نظام المعلومات والترفيه بوتنه، ما يقلل من الوقت الذي ينتظره السائق حتى يتم تحميل مستخدم Android.
تفعيل HAL للمستخدم
يجب تفعيل سمات HAL للمستخدمين صراحةً من خلال التأكّد من ضبط سمة system
android.car.user_hal_enabled
على true
.
(يمكنك إجراء ذلك في ملف car.mk
، لكي لا يكون هناك حاجة إلى
ضبطه يدويًا). تأكَّد من تفعيل user_hal_enabled=true
من خلال
تفريغ UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
يمكنك أيضًا التحقّق من user_hal_enabled
باستخدام adb shell
getprop android.car.user_hal_enabled
أو adb logcat
CarServiceHelper *:s
. إذا كان الموقع غير مفعَّل، يتم عرض رسالة مثل
ما يلي عند بدء system_server
:
I CarServiceHelper: Not using User HAL
لتفعيل user_hal_enabled
يدويًا، اضبط سمةandroid.car.user_hal_enabled
النظام
android.car.user_hal_enabled
وأعِد تشغيل
system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
يظهر الناتج logcat
على النحو التالي:
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
سمات HAL للمستخدم
سمات رحلة المستخدِم
تقدّم السمات التالية معلومات HAL لحالات دورة حياة المستخدِم ، ما يتيح مزامنة دورة حياة المستخدِم بين نظام Android ووحدة التحكّم الإلكترونية الخارجية. تستخدم هذه السمات بروتوكول طلب واستجابة، حيث يقدّم نظام Android طلبًا من خلال ضبط قيمة السمة ويردّ واجهة HAL من خلال إصدار حدث تغيير في السمة.
ملاحظة: عندما يكون HAL للمستخدم متوافقًا، يجب تنفيذ جميع السمات التالية.
موقع HAL | الوصف |
---|---|
INITIAL_USER_INFO (قراءة/كتابة) |
يستدعي نظام Android هذه السمة لتحديد مستخدم Android
الذي يبدأ النظام عند تشغيل الجهاز أو استئناف تشغيله من حالة
"التوقّف المؤقت في ذاكرة الوصول العشوائي" (STR). عند استدعاء HAL، يجب أن يستجيب بأحد
الخيارات التالية:
ملاحظة: إذا لم يستجِب HAL، يكون السلوك التلقائي هو التنفيذ بعد فترة مهلة (خمس ثوانٍ تلقائيًا)، ما يؤخّر عملية التمهيد. إذا ردّ HAL، ولكن تعذّر على نظام Android تنفيذ الإجراء (على سبيل المثال، إذا تم الوصول إلى الحد الأقصى لعدد المستخدمين)، يتم استخدام السلوك التلقائي. مثال: يبدأ نظام Android تلقائيًا في حساب المستخدم النشط الأخير عند بدء التشغيل. في حال رصد مفتاح تشويش لمستخدم مختلف، تلغي وحدة التحكّم في المحرك سمة HAL، وخلال بدء التشغيل، يبدّل نظام Android بدء التشغيل في هذا المستخدم المحدّد. |
SWITCH_USER (قراءة/كتابة) |
يتمّ استدعاء هذه السمة عند تبديل مستخدم Android النشط في المقدّمة.
يمكن أن يستدعي نظام Android أو HAL الخاصية لطلب التبديل إلى مستخدم آخر. حالات سير العمل الثلاث هي:
يستخدم سير العمل الحديث نهجًا للالتزام من مرحلتين لضمان تتميم عملية مزامنة نظام Android ووحدة التحكّم الإلكترونية الخارجية. عندما يبدأ Android عملية التبديل:
يجب أن ينتظر HAL حتى بعد استجابة مثال: أثناء التنقّل، يحاول السائق تبديل مستخدمي Android في واجهة مستخدم نظام المعلومات والترفيه. ومع ذلك، بما أنّ إعدادات مقعد السيارة مرتبطة بمستخدم Android، يتحرك المقعد أثناء تبديل المستخدم. وبالتالي، لا يؤكّد وحدة التحكّم الإلكترونية التي تتحكّم في المقاعد عملية التبديل، ويردّ HAL بخطأ، ولا يتم تبديل مستخدم Android.
سير العمل القديم هو مكالمة أحادية الاتجاه يتم إرسالها بعد تبديل المستخدم
(كي لا يتمكّن HAL من حظر التبديل). ولا يتم استدعاؤه إلا عند بدء التشغيل (بعد
تبديل المستخدم الأولي) أو للتطبيقات التي تستدعي
مثال: إذا كان أحد التطبيقات يستخدم
تبدأ سير العمل في المركبة من HAL، وليس من نظام Android:
مثال: استخدم "بدر" مفتاح "أسيل" لفتح السيارة،
وردّت HAL على طلب |
CREATE_USER (قراءة/كتابة) |
يستدعي نظام Android هذه السمة عند إنشاء مستخدم Android جديد (باستخدام واجهة برمجة التطبيقات CarUserManager.createUser() ).
يردّ HAL بـ مثال: ينقر السائق على رمز واجهة مستخدم نظام المعلومات والترفيه ل إنشاء حساب مستخدم جديد على Android. يؤدي ذلك إلى إرسال طلب إلى HAL وبقية أنظمة المركبات الفرعية. يتم إبلاغ وحدات التحكّم الإلكترونية بالمستخدم الذي تم إنشاؤه حديثًا. بعد ذلك، تربط الأنظمة الفرعية الأخرى ووحدات التحكّم الإلكترونية (ECU) معرّف المستخدم الداخلي بمعرّف مستخدم Android. |
REMOVE_USER (للكتابة فقط) |
يستدعي نظام Android هذا السمة بعد إزالة مستخدم Android (باستخدام الطريقة CarUserManager.removeUser() ).
هذه مكالمة أحادية الاتجاه، ولا يُتوقّع تلقّي ردّ من HAL. مثال: ينقر السائق لإزالة مستخدم Android حالي في واجهة مستخدم نظام المعلومات والترفيه. يتم إبلاغ HAL وأنظمة المركبات الفرعية والوحدات الإلكترونية للتحكم الأخرى بإزالة المستخدم حتى تتمكّن من إزالة معرّف المستخدم الداخلي. |
الخصائص الإضافية
في ما يلي سمات إضافية غير مرتبطة بحالات رحلة المستخدِم. ويمكن تنفيذ كل منهما بدون توفير واجهة برمجة التطبيقات لمستوى الحِزم للمستخدم.
موقع HAL | الوصف |
---|---|
USER_IDENTIFICATION_ASSOCIATION (قراءة/كتابة) |
استخدِم هذه السمة لربط أي مستخدم على Android بآلية تحديد هوية، مثل سلسلة مفاتيح أو هاتف. استخدِم هذه السمة نفسها لعمليات الربط
get أو set .
مثال: ينقر السائق على رمز واجهة مستخدم نظام المعلومات والترفيه لربط ملف تعريف مستخدم Android الحالي ( |
المكتبات المساعِدة
جميع العناصر المستخدَمة في رسائل الطلب والاستجابة (مثل
UserInfo
وInitialUserInfoRequest
InitialUSerInfoResponse
وما إلى ذلك) لها تمثيل على مستوى عالٍ
باستخدام struct
في C++، ولكن يجب تسطيح عملية الإزالة إلى
عناصر VehiclePropValue
عادية (اطّلِع على الأمثلة أدناه). لتسهيل عملية التطوير، يتم توفير مكتبة مساعدة مكتوبة بلغة C++ في AOSP لتحويل structs
User HAL
تلقائيًا إلى VehiclePropValue
(والعكس صحيح).
أمثلة
INITIAL_USER_INFO
مثال على الطلب (عند بدء التشغيل لأول مرة)
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 }
مثال على الردّ (إنشاء مستخدم مشرف)
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
يختلف الاسم الفعلي للفئات والسمات قليلاً، ولكن عملية سير العمل العامة هي نفسها، كما هو موضّح في الشكل:
الشكل 1: سير عمل خصائص HAL للمستخدم
مثال على طلب سير العمل الحديث
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) }
مثال على استجابة سير العمل الحديث
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 }
مثال على استجابة سير العمل الحديث بعد التبديل
تحدث هذه الاستجابة عادةً عند نجاح عملية تبديل 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) }
استجابة سير العمل الحديث بعد التبديل
يظهر هذا الردّ عادةً عند تعذُّر تبديل 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) }
مثال على طلب سير العمل القديم
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) }
مثال على طلب سير العمل للمركبات
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 }
استجابة سير العمل القديم بعد التبديل
تحدث هذه الاستجابة عادةً عند نجاح عملية تبديل 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) }
CREATE_USER
مثال على الطلب
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) }
مثال على الردّ
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
REMOVE_USER
مثال على الطلب
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
مثال على الإعداد (مفتاح السيارة المرتبط بالمستخدم 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 }