يقدّم نظام التشغيل Android 11 إمكانية استخدام AIDL مع واجهات HAL في Android، ما يجعله ممكنًا تنفيذ أجزاء من Android بدون HIDL. نقل واجهات برمجة التطبيقات لمستوى الحِزم الأساسية (HAL) لاستخدام AIDL حصريًا حيثما أمكن (يجب استخدام HIDL عندما تستخدم واجهات برمجة التطبيقات لمستوى الحِزم الأساسية في المصدر HIDL).
يجب أن تستخدم واجهات HAL التي تستخدم AIDL للتواصل بين مكونات إطار العمل، مثل تلك الواردة في
system.img
، ومكونات الأجهزة، مثل تلك الواردة في vendor.img
، مكتبة IDE الثابتة. ومع ذلك، للتواصل داخل قسم معيّن، على سبيل المثال، من معالج معالجة حدود المستوى (HAL) إلى آخر، لا يوجد أي قيود على آلية IPC التي يمكن استخدامها.
الحافز
تم استخدام لغة تعريف واجهة نظام Android لفترة أطول من لغة HIDL، ويتم استخدامها في العديد من الأماكن الأخرى، مثل بين مكونات إطار عمل Android أو في التطبيقات. والآن بعد أن أصبح تنسيق AIDL مستقرًا، أصبح من الممكن تنفيذ حِزمة كاملة باستخدام وقت تشغيل واحد لبروتوكول I/O بين العمليات. يحتوي AIDL أيضًا على نظام إصدار أفضل من HIDL. في ما يلي بعض مزايا IDE:
- يعني استخدام لغة واحدة لبروتوكول IPC أنّك ستحتاج إلى تعلم لغة واحدة فقط وتصحيح أخطاء التطبيقات و تحسينها وتأمينها.
- تتيح واجهة برمجة التطبيقات AIDL إمكانية إضافة إصدارات جديدة إلى الواجهات الحالية لمالكيها:
- يمكن للمالكين إضافة طرق إلى نهاية الواجهات أو حقول إلى العناصر القابلة للتقسيم. وهذا يعني أنّه من الأسهل إصدار الرمز البرمجي على مدار السنين، كما أنّ التكلفة على مدار السنة أدنى (يمكن تعديل الأنواع في مكانها ولا يلزم استخدام مكتبات إضافية لكل إصدار من الواجهة).
- يمكن إرفاق واجهات الإضافات في وقت التشغيل بدلاً من النظام النوع، لذا ليس من الضروري إعادة ربط الإضافات في مرحلة ما بعد المعالجة بإصدارات أحدث من الواجهات.
- يمكن استخدام واجهة AIDL حالية مباشرةً عندما يختار مالكها استقرارها. في السابق، كان يجب إنشاء نسخة كاملة من الواجهة في HIDL.
إنشاء التطبيق باستخدام وقت تشغيل AIDL
تتضمّن واجهة برمجة التطبيقات AIDL ثلاث واجهات خلفية مختلفة: Java وNDK وCPP. لاستخدام حزمة AIDL الثابتة،
استخدِم دائمًا نسخة النظام من libbinder
على system/lib*/libbinder.so
وشارِك في /dev/binder
. بالنسبة إلى الرمز البرمجي في صورة vendor
، يعني ذلك أنّه لا يمكن استخدام مكتبة
libbinder
(من حزمة VNDK) لأنّها تتضمّن واجهة برمجة تطبيقات C++
غير مستقرة ومكونات داخلية غير مستقرة. بدلاً من ذلك، يجب أن يستخدم رمز المورّد الأصلي واجهة برمجة التطبيقات لـ NDK
لـ AIDL، وأن يتم ربطه بـ libbinder_ndk
(الذي يتم دعمه من خلال نظام
libbinder.so
)، وأن يتم ربطه بمكتبات NDK التي تم إنشاؤها من خلال إدخالات aidl_interface
. لمعرفة أسماء الوحدات الدقيقة، يُرجى الاطّلاع على قواعد تسمية الوحدات.
كتابة واجهة HAL لـ AIDL
لاستخدام واجهة AIDL بين النظام والمورّد، تحتاج الواجهة إلى تغييرَين:
- يجب إضافة تعليق توضيحي باستخدام
@VintfStability
إلى كل تعريف نوع. - يجب أن يتضمّن نموذج بيان
aidl_interface
ما يلي:stability: "vintf",
.
ولا يمكن لأحد غير مالك الواجهة إجراء هذه التغييرات.
عند إجراء هذه التغييرات، يجب أن تكون الواجهة في
بيان VINTF لكي تعمل. اختبِر ذلك (والمتطلبات
المرتبطة به، مثل التحقّق من تجميد الواجهات التي تم إصدارها) باستخدام
اختبار VTS vts_treble_vintf_vendor_test
. يمكنك استخدام واجهة
@VintfStability
بدون هذه المتطلبات من خلال استدعاء إما
AIBinder_forceDowngradeToLocalStability
في الخلفية في NDK أو
android::Stability::forceDowngradeToLocalStability
في الخلفية في C++ أو
android.os.Binder#forceDowngradeToSystemStability
في الخلفية في Java
على عنصر ربط قبل إرساله إلى عملية أخرى.
بالإضافة إلى ذلك، لتحقيق أقصى قدر من إمكانية نقل الرموز البرمجية وتجنُّب المشاكل المحتملة، مثل المكتبات الإضافية غير الضرورية، يجب إيقاف الخلفية في لغة C++.
يُرجى العِلم أنّ استخدام backends
في مثال الرمز البرمجي التالي صحيح، لأنّه
تتوفر ثلاث خلفيات (Java وNDK وCPP). يوضّح الرمز كيفية
إيقاف الخلفية في ملف CPP:
aidl_interface: {
...
backends: {
cpp: {
enabled: false,
},
},
}
العثور على واجهات AIDL HAL
تتوفّر واجهات AIDL الثابتة لـ AOSP لـ HAL ضمن مجلدات aidl
في الدلائل الأساسية
نفسها التي تتوفّر فيها واجهات HIDL:
- يُستخدَم الرمز
hardware/interfaces
للواجهات التي يوفّرها الجهاز عادةً. -
frameworks/hardware/interfaces
مخصّص للواجهات العالية المستوى المقدَّمة للأجهزة. -
system/hardware/interfaces
مخصّص للواجهات ذات المستوى المنخفض المقدَّمة للأجهزة.
ضَع واجهات الإضافات في hardware/interfaces
المجلدات الفرعية الأخرى في vendor
أو hardware
.
واجهات الإضافات
يتضمّن Android مجموعة من واجهات AOSP الرسمية مع كل إصدار. عندما يريد شركاء Android إضافة إمكانات إلى هذه الواجهات، يجب ألا يغيّروا هذه الواجهات مباشرةً لأنّ ذلك يجعل وقت تشغيل Android غير متوافق مع وقت تشغيل Android من AOSP. تجنَّب تغيير هذه الواجهات حتى تظل صورة GSI تعمل.
يمكن تسجيل الإضافات بطريقتَين مختلفتَين:
- أثناء التشغيل، اطّلِع على واجهات الإضافات المرفقة.
- كوحدة مستقلة مسجَّلة على مستوى العالم وفي VINTF
بغض النظر عن كيفية تسجيل الإضافة، عندما تستخدم المكوّنات الخاصة بالمورّد (أي غير المكوّنة من الإصدار المصدر من AOSP) الواجهة، لا يمكن حدوث تعارضات في الدمج. ومع ذلك، عند إجراء تعديلات على الإصدارات اللاحقة لمكوّنات الإصدار المصدر من AOSP، يمكن أن يؤدي ذلك إلى حدوث تعارضات في الدمج، وننصح باستخدام الاستراتيجيات التالية:
- أرسِل إضافات الواجهة إلى AOSP في الإصدار التالي.
- إضافات واجهة التحميل التي تسمح بمزيد من المرونة (بدون تعارضات دمج) في الإصدار التالي
عناصر الحزمة الإضافية: ParcelableHolder
ParcelableHolder
هو مثيل لواجهة Parcelable
يمكنه
تضمين مثيل آخر من Parcelable
.
تتمثل حالة الاستخدام الرئيسية ParcelableHolder
في جعل Parcelable
قابلاً للتوسيع.
على سبيل المثال، الصورة التي يتوقّع منتشِرو الأجهزة أن يتمكّنوا من توسيع نطاق Parcelable
أو AospDefinedParcelable
المحدّدَين في AOSP لتشمل ميزات قيّمة.
استخدِم واجهة ParcelableHolder
لتوسيع Parcelable
باستخدام ميزات ملفّات Parcelable
التي تضيف قيمة. تحتوي واجهة ParcelableHolder
على مثيل
Parcelable
. إذا حاولت إضافة حقول إلى Parcelable
مباشرةً، يؤدي ذلك إلى
حدوث خطأ:
parcelable AospDefinedParcelable {
int a;
String b;
String x; // ERROR: added by a device implementer
int[] y; // added by a device implementer
}
كما هو موضّح في الرمز البرمجي السابق، لا يمكن تنفيذ هذه الممارسة لأنّ الحقول التيأضافها مُنفِّذ الجهاز قد تتعارض مع Parcelable
عند تعديله في الإصدارات التالية من Android.
باستخدام ParcelableHolder
، يمكن لمالك قطعة أرض تحديد نقطة بدء التمديد في مثيل Parcelable
:
parcelable AospDefinedParcelable {
int a;
String b;
ParcelableHolder extension;
}
بعد ذلك، يمكن لمنفّذِي الأجهزة تحديد مثيل Parcelable
الخاص بهم
لإضافتهم:
parcelable OemDefinedParcelable {
String x;
int[] y;
}
يمكن إرفاق مثيل Parcelable
الجديد بالملف الأصلي
Parcelable
باستخدام الحقل ParcelableHolder
:
// Java
AospDefinedParcelable ap = ...;
OemDefinedParcelable op = new OemDefinedParcelable();
op.x = ...;
op.y = ...;
ap.extension.setParcelable(op);
...
OemDefinedParcelable op = ap.extension.getParcelable(OemDefinedParcelable.class);
// C++
AospDefinedParcelable ap;
OemDefinedParcelable op;
std::shared_ptr<OemDefinedParcelable> op_ptr = make_shared<OemDefinedParcelable>();
ap.extension.setParcelable(op);
ap.extension.setParcelable(op_ptr);
...
std::shared_ptr<OemDefinedParcelable> op_ptr;
ap.extension.getParcelable(&op_ptr);
// NDK
AospDefinedParcelable ap;
OemDefinedParcelable op;
ap.extension.setParcelable(op);
...
std::optional<OemDefinedParcelable> op;
ap.extension.getParcelable(&op);
// Rust
let mut ap = AospDefinedParcelable { .. };
let op = Rc::new(OemDefinedParcelable { .. });
ap.extension.set_parcelable(Rc::clone(&op));
...
let op = ap.extension.get_parcelable::<OemDefinedParcelable>();
أسماء نُسخ خادم HAL في AIDL
وفقًا للاتفاقية، تتضمّن خدمات HAL في AIDL اسم مثيل بالشكل
$package.$type/$instance
. على سبيل المثال، يتم تسجيل مثيل HAL الخاص بالهزّاز
على أنّه android.hardware.vibrator.IVibrator/default
.
كتابة خادم HAL لواجهة برمجة التطبيقات AIDL
@VintfStability
يجب تحديد خوادم AIDL في بيان VINTF، على سبيل المثال:
<hal format="aidl">
<name>android.hardware.vibrator</name>
<version>1</version>
<fqname>IVibrator/default</fqname>
</hal>
بخلاف ذلك، يجب تسجيل خدمة AIDL بشكلٍ طبيعي. عند إجراء اختبارات VTS، من المتوقّع أن تكون جميع واجهات برمجة التطبيقات HAL لـ AIDL المعلَن عنها متوفرة.
كتابة برنامج AIDL
يجب أن يعلن عملاء AIDL عن أنفسهم في مصفوفة التوافق، على سبيل المثال:
<hal format="aidl" optional="true">
<name>android.hardware.vibrator</name>
<version>1-2</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
تحويل HAL حالي من HIDL إلى AIDL
استخدِم أداة hidl2aidl
لتحويل واجهة HIDL إلى AIDL.
ميزات hidl2aidl
:
- أنشئ ملفات AIDL (
.aidl
) استنادًا إلى ملفات HAL (.hal
) لملف الحزمة المُعطى. - أنشئ قواعد إنشاء لحزمة AIDL التي تم إنشاؤها حديثًا مع تفعيل جميع الخلفيات.
- أنشئ طرق ترجمة في الخلفيات Java وCPP وNDK لترجمة من أنواع HIDL إلى أنواع AIDL.
- أنشئ قواعد إنشاء لمكتبات الترجمة مع التبعيات المطلوبة.
- أنشئ تأكيدات ثابتة لضمان أنّ أدوات سرد HIDL وAIDL تتضمّن القيم نفسها في الخلفيات CPP وNDK.
اتّبِع الخطوات التالية لتحويل حِزمة من ملفات HAL إلى ملفات AIDL:
أنشئ الأداة في
system/tools/hidl/hidl2aidl
.يقدّم إنشاء هذه الأداة من أحدث مصدر أفضل تجربة كاملة. يمكنك استخدام أحدث إصدار لتحويل الواجهات في الإصدارات السابقة من الفروع:
m hidl2aidl
نفِّذ الأداة مع دليل إخراج متبوعًا بالحزمة التي تريد تحويلها.
يمكنك اختياريًا استخدام الوسيطة
-l
لإضافة محتوى ملف ترخيص جديد إلى أعلى جميع الملفات التي تم إنشاؤها. احرص على استخدام الترخيص والتاريخ الصحيحَين:hidl2aidl -o <output directory> -l <file with license> <package>
مثلاً:
hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
اطّلِع على الملفات التي تم إنشاؤها وأصلِح أي مشاكل في عملية التحويل:
- يحتوي
conversion.log
على أي مشاكل لم يتم حلّها ويجب حلّها أولاً. - قد تحتوي ملفات AIDL التي تم إنشاؤها على تحذيرات واقتراحات تحتاج إلى اتّخاذ إجراء. تبدأ هذه التعليقات بالرمز
//
. - تنظيف الحزمة وإجراء تحسينات عليها
- اطّلِع على التعليق التوضيحي
@JavaDerive
للاطّلاع على الميزات التي قد تكون مطلوبة، مثلtoString
أوequals
.
- يحتوي
أنشئ الاستهدافات التي تحتاج إليها فقط:
- أوقِف الخلفيات التي لن يتم استخدامها. يُفضَّل استخدام الخلفية في NDK بدلاً من الخلفية في لغة برمجة C++، راجِع الإنشاء وفقًا لوقت تشغيل AIDL.
- أزِل مكتبات الترجمة أو أيّ من الرموز التي تم إنشاؤها ولن يتم استخدامها.
اطّلِع على الاختلافات الرئيسية بين AIDL وHIDL:
- يؤدي استخدام
Status
والاستثناءات المضمّنة في AIDL إلى تحسين الواجهة عادةً وإزالة الحاجة إلى نوع حالة آخر خاص بالواجهة. - لا تكون وسيطات واجهة AIDL في الطرق
@nullable
تلقائيًا كما كانت في HIDL.
- يؤدي استخدام
سياسة SEPolicy لحِزم HAL لـ لغة تعريف واجهة نظام Android
يجب أن يتضمّن نوع خدمة AIDL المرئي لرمز المورّد سمة
hal_service_type
. بخلاف ذلك، تكون إعدادات سياسة الأمان مماثلة
لأي خدمة أخرى من خدمات AIDL (على الرغم من توفُّر سمات خاصة لواجهة HAL). في ما يلي مثال على تعريف سياق خدمة HAL:
type hal_foo_service, service_manager_type, hal_service_type;
بالنسبة إلى معظم الخدمات التي تحدّدها المنصة، سبق أن تمت إضافة سياق الخدمة بنوع
صحيح (على سبيل المثال، سبق أن تم وضع علامة على android.hardware.foo.IFoo/default
بصفتها hal_foo_service
). ومع ذلك، إذا كان أحد عملاء إطار العمل يتيح
أسماء نُسخ متعددة، يجب إضافة أسماء نُسخ إضافية فيملف service_contexts
الخاص بالجهاز:
android.hardware.foo.IFoo/custom_instance u:object_r:hal_foo_service:s0
عند إنشاء نوع جديد من HAL، يجب إضافة سمات HAL. قد تكون سمة HAL
معيّنة مرتبطة بأنواع خدمات متعددة (يمكن أن يكون لكل منها
مثيلات متعددة كما ناقشنا للتو). بالنسبة إلى HAL، foo
، هناك
hal_attribute(foo)
. يحدِّد هذا الماكرو السمتَين hal_foo_client
و
hal_foo_server
. بالنسبة إلى نطاق معيّن، تربط الوحدات النمطية hal_client_domain
و
hal_server_domain
نطاقًا بسمة HAL معيّنة. على سبيل المثال، يتوافق خادم النظام الذي يكون عميلًا لواجهة HAL هذه مع السياسة
hal_client_domain(system_server, hal_foo)
. يتضمّن خادم HAL بالمثل
hal_server_domain(my_hal_domain, hal_foo)
.
عادةً، بالنسبة إلى سمة HAL معيّنة، يمكنك أيضًا إنشاء نطاق مثل
hal_foo_default
للإشارة إلى HAL أو مثال عليه. ومع ذلك، تستخدم بعض الأجهزة
هذه النطاقات لخوادم خاصة بها. لا يهم التمييز بين نطاقات
الخوادم المتعددة إلا إذا كانت هناك خوادم متعددة تقدّم
الواجهة نفسها وتحتاج إلى مجموعة أذونات مختلفة في عمليات التنفيذ.
في كل هذه الوحدات النمطية، لا يمثّل hal_foo
عنصر سياسة أمان الخدمات. بدلاً من ذلك، تستخدم هذه الوحدات النمطية هذا الرمز المميّز للإشارة إلى مجموعة السمات المرتبطة
بزوج خادم عميل.
ومع ذلك، حتى الآن، لم يتم ربط hal_foo_service
وhal_foo
(زوج السمات من
hal_attribute(foo)
). يتم ربط سمة HAL
بخدمات HAL في AIDL باستخدام وحدة الماكرو hal_attribute_service
(تستخدم خدمات HAL في HIDL
وحدة الماكرو hal_attribute_hwservice
)، على سبيل المثال،
hal_attribute_service(hal_foo, hal_foo_service)
. وهذا يعني أنّه يمكن لعمليات hal_foo_client
الحصول على HAL، ويمكن لعمليات hal_foo_server
تسجيل HAL. يُنفّذ مدير السياق (servicemanager
) قواعد التسجيل هذه.
قد لا تتطابق أسماء الخدمات دائمًا مع سمات HAL، على سبيل المثال،
hal_attribute_service(hal_foo, hal_foo2_service)
. بشكل عام، يمكنك إزالة hal_foo2_service
واستخدام hal_foo_service
في جميع سياقات
الخدمة، لأنّه
يشير ذلك إلى أنّه يتم استخدام الخدمات معًا دائمًا. عندما تضبط HALs عدّة نُسخ من hal_attribute_service
، يكون ذلك لأنّ اسم سمة HAL الأصلي ليس عامًا بما يكفي ولا يمكن تغييره.
بعد تجميع كل هذه العناصر معًا، يظهر مثال على HAL على النحو التالي:
public/attributes:
// define hal_foo, hal_foo_client, hal_foo_server
hal_attribute(foo)
public/service.te
// define hal_foo_service
type hal_foo_service, hal_service_type, protected_service, service_manager_type
public/hal_foo.te:
// allow binder connection from client to server
binder_call(hal_foo_client, hal_foo_server)
// allow client to find the service, allow server to register the service
hal_attribute_service(hal_foo, hal_foo_service)
// allow binder communication from server to service_manager
binder_use(hal_foo_server)
private/service_contexts:
// bind an AIDL service name to the selinux type
android.hardware.foo.IFooXxxx/default u:object_r:hal_foo_service:s0
private/<some_domain>.te:
// let this domain use the hal service
binder_use(some_domain)
hal_client_domain(some_domain, hal_foo)
vendor/<some_hal_server_domain>.te
// let this domain serve the hal service
hal_server_domain(some_hal_server_domain, hal_foo)
واجهات الإضافات المرفقة
يمكن إرفاق إضافة بأي واجهة ربط، سواء كانت واجهة على مستوى أعلى مسجّلة مباشرةً مع مدير الخدمة أو واجهة فرعية. عند الحصول على إضافة، عليك التأكّد من أنّ نوع الإضافة هو كما هو متوقّع. لا يمكنك ضبط الإضافات إلا من العملية التي تعرِض رابطًا.
استخدِم الإضافات المرفقة عندما تعدّل إضافة وظيفية HAL حالية. عندما تكون هناك حاجة إلى قدرة جديدة تمامًا، لا تكون هذه الآلية ضرورية، ويمكنك تسجيل واجهة إضافة مع مدير الخدمة مباشرةً. تكون واجهات الإضافات المُرفَقة أكثر منطقية عند إرفاقها بواجهات فرعية، لأنّ هذه الهرميات يمكن أن تكون معقدة أو متعددة النُسخ. إنّ استخدام إضافة عالمية لعكس التسلسل الهرمي لواجهة الربط لخدمة أخرى يتطلّب توثيقًا واسع النطاق لتوفير إمكانات مماثلة للإضافات المرتبطة مباشرةً.
لضبط إضافة على أداة ربط، استخدِم واجهات برمجة التطبيقات التالية:
- الخلفية في NDK:
AIBinder_setExtension
- Java backend:
android.os.Binder.setExtension
- الخلفية في "التكلفة لكل مكالمة هاتفية":
android::Binder::setExtension
- الخلفية في Rust:
binder::Binder::set_extension
للحصول على إضافة في رابط، استخدِم واجهات برمجة التطبيقات التالية:
- الخلفية في NDK:
AIBinder_getExtension
- Java backend:
android.os.IBinder.getExtension
- الخلفية في "التكلفة لكل مكالمة هاتفية":
android::IBinder::getExtension
- الخلفية في Rust:
binder::Binder::get_extension
يمكنك العثور على مزيد من المعلومات عن واجهات برمجة التطبيقات هذه في مستندات دالة
getExtension
في الخلفية المقابلة. يمكنك الاطّلاع على مثال على كيفية استخدام
الإضافات في
hardware/interfaces/tests/extension/vibrator
.
الاختلافات الرئيسية بين AIDL وHIDL
عند استخدام واجهات HAL في AIDL أو استخدام واجهات HAL في AIDL، يجب الانتباه إلى الاختلافات مقارنةً بكتابة واجهات HAL في HIDL.
- يشبه بناء جملة لغة AIDL لغة Java. تشبه بنية HIDL بنية C++.
- تحتوي جميع واجهات AIDL على حالات خطأ مضمّنة. بدلاً من إنشاء
أنواع حالة مخصّصة، أنشئ أرقامًا صحيحة ثابتة للحالة في ملفات الواجهات واستخدِم
EX_SERVICE_SPECIFIC
في الخلفيات CPP وNDK وServiceSpecificException
في الخلفية Java. اطّلِع على معالجة الخطأ. - لا يبدأ AIDL مجموعات مؤشرات الترابط تلقائيًا عند إرسال عناصر الربط. يجب بدؤها يدويًا (راجِع إدارة سلاسل المحادثات).
- لا تُوقِف واجهة برمجة التطبيقات AIDL عمليات النقل عند حدوث أخطاء غير محدَّدة (توقِف واجهة برمجة التطبيقات HIDL
Return
عمليات النقل عند حدوث أخطاء غير محدَّدة). - يمكن أن تحدِّد واجهة برمجة التطبيقات AIDL نوعًا واحدًا فقط لكل ملف.
- يمكن تحديد وسيطات AIDL على أنّها
in
أوout
أوinout
بالإضافة إلى مَعلمة الإخراج (لا تتوفّر عمليات استدعاء للوظائف المتزامنة). - يستخدم AIDL
fd
كنوع أساسي بدلاً منhandle
. - يستخدم HIDL الإصدارات الرئيسية للتغييرات غير المتوافقة والإصدارات الثانوية للتغييرات
المتوافقة. في AIDL، يتم إجراء التغييرات المتوافقة مع الإصدارات القديمة في مكانها.
لا يتضمّن تنسيق AIDL مفهومًا صريحًا للإصدارات الرئيسية، بل يتم بدلاً من ذلك دمجه في أسماء الحِزم. على سبيل المثال، قد يستخدم AIDL اسم الحزمة
bluetooth2
. - لا يكتسب AIDL الأولوية في الوقت الفعلي تلقائيًا. يجب استخدام الدالة
setInheritRt
لكل رابط لتفعيل اكتساب الأولوية في الوقت الفعلي.
اختبارات مجموعة اختبار المورّد (VTS) لواجهة برمجة التطبيقات لنظام التشغيل
يعتمد Android على مجموعة اختبار المورّدين (VTS) للتحقّق من صحة عمليات تنفيذ HAL المتوقّعة. تساعد تقنية VTS في ضمان توافق Android مع الإصدارات القديمة من تطبيقات المورّدين. إنّ عمليات التنفيذ التي لا تجتاز اختبار VTS تواجه مشاكل توافق معروفة قد تمنع عملها مع الإصدارات القادمة من نظام التشغيل.
هناك جزءان رئيسيان من نظام التحكّم في الرؤية (VTS) لأجهزة HAL.
1. التأكّد من أنّ واجهات HAL على الجهاز معروفة ومتوقّعة من قِبل Android
يمكن العثور على هذه المجموعة من الاختبارات في
test/vts-testcase/hal/treble/vintf
.
تتحمّل هذه الاختبارات مسؤولية التحقّق مما يلي:
- يتم تجميد كل واجهة
@VintfStability
يتم الإعلان عنها في بيان VINTF عند إصدار معروف. يضمن ذلك توافق كلا جانبَي الواجهة على التعريف الدقيق لهذا الإصدار من الواجهة. هذا الإجراء ضروري للتشغيل الأساسي. - تتوفّر جميع واجهات HAL التي تم الإعلان عنها في بيان VINTF على هذا الجهاز. يجب أن يتمكّن أيّ مستخدم لديه أذونات كافية لاستخدام خدمة HAL مُعلَن عنها من الحصول على هذه الخدمات واستخدامها في أيّ وقت.
- إنّ جميع واجهات HAL التي تم الإعلان عنها في بيان VINTF تعرِض إصدار الواجهة الذي تم الإعلان عنه في البيان.
- لا يتم عرض أي واجهات HAL متوقّفة نهائيًا على الجهاز. سيتوقف نظام التشغيل Android عن إتاحة استخدام الإصدارات الأقدم من واجهات HAL كما هو موضّح في دورة حياة FCM.
- توفُّر واجهات برمجة التطبيقات لواجهة HAL المطلوبة على الجهاز تكون بعض واجهات HAL مطلوبة لكي يعمل Android بشكل صحيح.
2- التحقّق من السلوك المتوقّع لكل HAL
تحتوي كل واجهة HAL على اختبارات VTS الخاصة بها للتحقّق من السلوك المتوقّع من العميل. يتم تشغيل حالات الاختبار على كل مثيل لواجهة HAL معلَن عنها وفرض سلوك معيّن استنادًا إلى إصدار الواجهة الذي تم تنفيذه.
تحاول هذه الاختبارات تغطية كل جانب من جوانب تنفيذ HAL الذي يعتمد عليه إطار عمل Android أو قد يعتمد عليه في المستقبل.
وتشمل هذه الاختبارات التحقّق من توفّر الميزات، ومعالجة الأخطاء، وأي سلوك آخر قد يتوقّعه العميل من الخدمة.
المعالم الرئيسية لنظام التحكّم في الرؤية (VTS) لتطوير HAL
من المتوقّع أن يتم تعديل اختبارات VTS عند إنشاء واجهة HAL أو تعديلها في Android.
يجب أن تكون اختبارات VTS قد اكتملت وجاهزة للتحقّق من عمليات تنفيذ المورّدين قبل تجميدها لإصدارات Android Vendor API. ويجب أن تكون جاهزة قبل تجميد الواجهات حتى يتمكّن المطوّرون من إنشاء عمليات التنفيذ الخاصة بهم والتحقق منها وتقديم ملاحظاتهم إلى مطوّري واجهةHAL.
ميزة "التتبّع في الوقت الفعلي" على Cuttlefish
عندما لا يتوفّر الجهاز، يستخدم Android Cuttlefish كأداة تطوير لواجهات HAL. يتيح ذلك اختبار سلامة النقل والاختبار التكاملي لنظام Android على نطاق واسع.
تُجري أداة hal_implementation_test
اختبارات للتأكّد من أنّ Cuttlefish يتضمّن أحدث إصدارات واجهة HAL للتأكّد من أنّ نظام Android جاهز للتعامل مع الواجهات الجديدة ومن أنّ اختبارات VTS جاهزة لاختبار عمليات التنفيذ الجديدة لمورّدي الأجهزة فور توفّر الأجهزة الجديدة.