تحديد إصدارات الواجهة

يتطلب HIDL إصدار نُسخ من كل واجهة مكتوبة بـ HIDL. بعد HAL نشر واجهة المستخدم، وتم تجميدها، ويجب إجراء أي تغييرات أخرى على بإصدار جديد من تلك الواجهة. وعلى الرغم من أنه لا يمكن ربط واجهة منشورة يمكن توسيعه باستخدام واجهة أخرى.

بنية رمز HIDL

يتم تنظيم رمز HIDL في صورة يحددها المستخدم الأنواع والواجهات والحزم:

  • الأنواع من تحديد المستخدم (UDTs): يوفر HIDL الوصول إلى مجموعة من أنواع البيانات الأولية التي يمكن استخدامها لإنشاء أنواع أكثر تعقيدًا من خلال الهياكل والاتحادات والتعدادات. يتم تمرير رموز UDT إلى طرق ويمكن تحديدها على مستوى الحزمة (شائعة لجميع الواجهات) أو محليًا على إحدى الواجهات.
  • الواجهات: وهي وحدة أساسية في HIDL، وهي واجهة من UDT وإعلانات الطريقة. يمكن أن تكتسب الواجهات أيضًا من واجهة أخرى.
  • الحِزم: تنظِّم واجهات HIDL ذات الصلة والبيانات. في الأنواع التي تعمل عليها. يتم تحديد الحزمة بواسطة اسم وإصدار ما يلي:
    • ملف تعريف من نوع بيانات باسم types.hal.
    • لا تتوفّر واجهات أو أكثر، كلٌّ منها في ملف .hal الخاص بها.

يحتوي ملف تعريف نوع البيانات types.hal على الأحرف UDT فقط (جميع UDT على مستوى الحزمة في ملف واحد). التمثيلات في الهدف متاحة لجميع الواجهات في الحزمة.

فلسفة تحديد الإصدارات

حزمة HIDL (مثل android.hardware.nfc)، بعد أن يتم منشور لنسخة معيَّنة (مثل 1.0)، غير قابل للتغيير. هو/هي ولا يمكن تغييره. التعديلات على الواجهات في الحزمة أو أي لا يمكن أن تحدث التغييرات في المعرِّفات الموحدة (UDT) إلا في حزمة أخرى.

في HIDL، ينطبق تحديد الإصدارات على مستوى الحزمة، وليس على مستوى الواجهة، وجميع الواجهات والواجهات UDT في الحزمة تشترك في الإصدار نفسه. طرد تتبع النُسخ الدلالية الإصدارات بدون مستوى التصحيح ومكوّنات البيانات الوصفية للإصدار. في حزمة معينة، يشير الاصطدام الثانوي إلى الإصدار الجديد من تتوافق الحزمة مع الإصدارات القديمة مع الحزمة القديمة و الإصدار من الاصطدام إلى أن الإصدار الجديد من الحزمة ليس التوافق مع الإصدارات القديمة مع الحزمة القديمة.

من الناحية النظرية، يمكن أن ترتبط الحزمة بحزمة أخرى بإحدى الطرق التالية:

  • على الإطلاق:
  • قابلية التوسّع المتوافقة مع الإصدارات القديمة على مستوى الحزمة: هذا النمط يحدث في عمليات الأعلى الجديدة ذات الإصدار الثانوي (المراجعة اللاحقة) لحزمة؛ فإن الحزمة الجديدة لها نفس الاسم وإصدار رئيسي كالحزمة القديمة، ولكن رقم الإصدار الثانوي الأعلى. من الناحية الوظيفية، تعد الحزمة الجديدة أفضل من الحزمة القديمة حزمة، المعنى:
    • توجد واجهات ذات مستوى أعلى للحزمة الرئيسية في الحزمة الجديدة، على الرغم من أن الواجهات قد تتضمن طرقًا جديدة، إلا أن UDT الجديدة المحلية للواجهة ( امتداد على مستوى الواجهة الموضح أدناه)، وواجهات UDT جديدة في types.hal
    • يمكن أيضًا إضافة واجهات جديدة إلى الحزمة الجديدة.
    • جميع أنواع البيانات الخاصة بالحزمة الرئيسية موجودة في الحزمة الجديدة يمكن التعامل معها من خلال الطرق (التي ربما أعيد تنفيذها) من الحزمة القديمة.
    • يمكن أيضًا إضافة أنواع بيانات جديدة لاستخدامها من خلال أي من الطريقتين الجديدتين لتحسين الأداء. الواجهات الحالية أو حسب الواجهات الجديدة.
  • قابلية التوسّع المتوافقة مع الإصدارات القديمة على مستوى الواجهة: يمكن أيضًا لحزمة توسيع الحزمة الأصلية أن تتكون من وحدات منفصلة منطقيًا الواجهات التي توفّر ببساطة وظائف إضافية، وليس الوظائف الأساسية لهذا الغرض، قد يكون ما يلي مرغوبًا فيه:
    • تلجأ الواجهات في الحزمة الجديدة إلى أنواع بيانات طرد.
    • يمكن أن تعمل الواجهات في الحزمة الجديدة على تمديد الواجهات القديمة لواحد أو أكثر الحزم.
  • توسيع نطاق عدم التوافق الأصلي مع الأنظمة القديمة. هذا هو وارتفاع الإصدار الرئيسي للحزمة، وليست هناك حاجة إلى أي ارتباط بين الاثنين. وبقدر ما يوجد، يمكن التعبير عنه بمجموعة من من الإصدار الأقدم للحزمة، واكتساب مجموعة فرعية من وواجهات الحزمة القديمة.

هيكلة الواجهة

للحصول على واجهة منظمة بشكل جيد، يمكن إضافة أنواع جديدة من الوظائف ليست جزءًا من التصميم الأصلي يجب أن تتطلب تعديلاً لرخصة HIDL من واجهة pyplot. وعلى العكس، إذا كنت تستطيع أو تتوقع إجراء تغيير من كلا جانبي الواجهة التي تقدّم وظائف جديدة بدون تغيير الواجهة نفسها، فإن الواجهة ليست مهيكلة.

يدعم Treble مكونات النظام والمورِّد التي تم تجميعها بشكل منفصل والتي vendor.img على أحد الأجهزة وsystem.img يمكن مجمعة بشكل منفصل. كل التفاعلات بين vendor.img و يجب تحديد system.img بشكل صريح ودقيق حتى تتمكّن من واستمروا في العمل لسنوات عديدة. ويشمل ذلك العديد من مساحات عرض واجهة برمجة التطبيقات، ولكن هو آلية IPC التي يستخدمها HIDL للاتصال البيني للعمليات على الحد system.img/vendor.img

المتطلبات

يجب تحديد جميع البيانات التي يتم تمريرها من خلال HIDL بشكل صريح. لضمان والتنفيذ والعميل من مواصلة العمل معًا حتى عند تجميع بشكل منفصل أو إذا تم تطويره بشكل مستقل، فيجب أن تلتزم البيانات بما يلي المتطلبات:

  • يمكن وصفها في HIDL مباشرةً (باستخدام تعدادات structs، وما إلى ذلك) مع والأسماء الدلالية والمعنى.
  • يمكن وصفه وفقًا لمعيار عام مثل ISO/IEC 7816.
  • يمكن وصفه بواسطة تخطيط الأجهزة القياسية أو الفعلية.
  • يمكن أن تكون بيانات مبهمة (مثل المفاتيح العامة وأرقام التعريف وما إلى ذلك) إذا لزم الأمر.

في حال استخدام بيانات مبهمة، يجب قراءتها فقط على جانب واحد من شهادة HIDL من واجهة pyplot. على سبيل المثال، إذا أعطى الرمز vendor.img مكوّنًا على system.img رسالة سلسلة أو vec<uint8_t> البيانات التي لا يمكن تحليلها باستخدام system.img نفسه مُمْكِنْ يتم إرسالها مرة أخرى إلى vendor.img فقط لتفسيرها. متى تمرير قيمة من vendor.img إلى رمز البائع في system.img أو إلى جهاز آخر، تنسيق البيانات وكيفية ذلك إلى أن يُفسَّر يجب وصفه بدقة ويظل جزءًا من من واجهة pyplot.

الإرشادات

ينبغي أن تكون قادرًا على كتابة تنفيذ أو عميل لـ HAL باستخدام ملفات .hal (أي لن تحتاج إلى إلقاء نظرة على مصدر Android أو إلى والمعايير القياسية). ننصح بتحديد السلوك المطلوب بدقة. عبارات مثل لأنّ "التطبيق قد يكون A أو B" بتشجيع عمليات التنفيذ لتصبح متشابكة مع العملاء الذين تم تطويرهم معهم.

تنسيق رمز HIDL

تشمل HIDL الحزم الأساسية وحزم البائع.

واجهات HIDL الأساسية هي تلك التي تحدّدها Google. الطرود التي ينتمي إليها التي تبدأ بـ android.hardware. وتسميتها من قبل النظام الفرعي، مع مستويات متداخلة من التسمية. على سبيل المثال، تتم تسمية حزمة NFC android.hardware.nfc وحزمة الكاميرا هي android.hardware.camera بشكل عام، الحزمة الأساسية لها اسم android.hardware.[name1].[name2]... حزم HIDL لها إصدار بالإضافة إلى اسمها. على سبيل المثال، تتضمن الحزمة قد يكون الإصدار android.hardware.camera متوفرًا في الإصدار 3.4. هذا هو مهم، حيث يؤثر إصدار الحزمة في موضعها في شجرة المصدر.

يتم وضع جميع الحِزم الأساسية ضمن hardware/interfaces/ في نظام التصميم. الطرد android.hardware.[name1].[name2]... في الإصدار $m.$n أقل من hardware/interfaces/name1/name2/.../$m.$n/؛ طرد الإصدار 3.4 من android.hardware.camera متوفّر في الدليل. hardware/interfaces/camera/3.4/. يوجد تعيين غير قابل للتغيير بين بادئة الحزمة android.hardware. والمسار hardware/interfaces/.

الحزم غير الأساسية (المورِّدون) هي تلك التي ينتجها مورّد المنظومة على الرقاقة (SoC) أو ODM. تشير رسالة الأشكال البيانية للحزم غير الأساسية هي بادئة vendor.$(VENDOR).hardware. حيث $(VENDOR)تشير إلى مورّد منظومة على الرقاقة (SoC) أو المصنّع الأصلي للجهاز أو المصنّع الأصلي للجهاز. يؤدي هذا إلى ربط المسار vendor/$(VENDOR)/interfaces في الشجرة (عملية الربط هذه أيضًا غير قابل للتغيير).

أسماء أنواع محدّدة من قِبل المستخدم مؤهلة بالكامل

في HIDL، يكون لكل UDT اسم مؤهل بالكامل يتكون من اسم UDT، اسم الحزمة حيث يتم تعريف UDT وإصدار الحزمة. تشير رسالة الأشكال البيانية لا يتم استخدام اسم مؤهل بالكامل إلا عندما يتم الإعلان عن الحالات من النوع وليس حيث يتم تعريف النوع نفسه. على سبيل المثال، لنفترض أن الحزمة تحدِّد النسخة 1.0 من android.hardware.nfc, بنية. باسم NfcData. في موقع البيان (سواء في types.hal أو ضمن بيان واجهة)، فإن البيان ينص ببساطة على:

struct NfcData {
    vec<uint8_t> data;
};

عند الإعلان عن مثيل من هذا النوع (سواء داخل بنية بيانات أو كمعلمة طريقة)، فاستخدم اسم النوع المؤهل بالكامل:

android.hardware.nfc@1.0::NfcData

الصيغة العامة هي PACKAGE@VERSION::UDT، حيث:

  • PACKAGE هو الاسم المفصول بالنقاط لحزمة HIDL. (مثال: android.hardware.nfc).
  • VERSION هو الإصدارMajor.minor-version المفصول بالنقاط تنسيق الحزمة (على سبيل المثال، 1.0).
  • UDT هو الاسم المفصول بالنقاط لـ HIDL UDT. نظرًا لأن HIDL تدعم واجهات UDT وHIDL المدمجة، يمكن أن تحتوي على UDT (نوع من إعلان متداخل)، تُستخدم النقاط للوصول إلى الأسماء.

على سبيل المثال، إذا تم تحديد التعريف المتداخل التالي في علامة أنواع الملف في إصدار الحزمة android.hardware.example 1.0:

// types.hal
package android.hardware.example@1.0;
struct Foo {
    struct Bar {
        // …
    };
    Bar cheers;
};

اسم Bar المؤهل بالكامل هو android.hardware.example@1.0::Foo.Bar إذا، بالإضافة إلى التواجد في للحزمة أعلاه، كان الإعلان المتداخل في واجهة تسمى IQuux:

// IQuux.hal
package android.hardware.example@1.0;
interface IQuux {
    struct Foo {
        struct Bar {
            // …
        };
        Bar cheers;
    };
    doSomething(Foo f) generates (Foo.Bar fb);
};

اسم Bar المؤهل بالكامل هو android.hardware.example@1.0::IQuux.Foo.Bar

وفي كلتا الحالتين، يمكن الإشارة إلى Bar على أنّه Bar فقط. في نطاق بيان Foo في الطرد أو مستوى الواجهة، يجب الرجوع إلى Bar من خلال Foo: Foo.Bar، كما في إعلان الطريقة doSomething أعلاه. بدلاً من ذلك، يمكنك الإعلان عن الطريقة بشكل مطول على النحو التالي:

// IQuux.hal
doSomething(android.hardware.example@1.0::IQuux.Foo f) generates (android.hardware.example@1.0::IQuux.Foo.Bar fb);

قيم تعداد مؤهَّلة بالكامل

إذا كان UDT نوع تعداد، فإن كل قيمة من نوع التعداد يكون لها اسم مؤهل بالكامل يبدأ بالاسم المؤهل بالكامل لنوع التعداد، متبوعة بعلامة النقطتين، ثم متبوعة باسم قيمة التعداد. على سبيل المثال: افتراض الحزمة android.hardware.nfc, الإصدار 1.0 إلى تحديد نوع التعداد NfcStatus:

enum NfcStatus {
    STATUS_OK,
    STATUS_FAILED
};

عند الإشارة إلى STATUS_OK، يكون الاسم المؤهّل بالكامل هو:

android.hardware.nfc@1.0::NfcStatus:STATUS_OK

الصيغة العامة هي PACKAGE@VERSION::UDT:VALUE, حيث:

  • PACKAGE@VERSION::UDT هو نفس الاسم المؤهل بالكامل لنوع التعداد.
  • VALUE هو اسم القيمة.

قواعد الاستنتاج التلقائي

لا يلزم تحديد اسم UDT مؤهل بالكامل. يمكن لاسم UDT احذف ما يلي بأمان:

  • الحزمة، مثل @1.0::IFoo.Type
  • كلاً من الحزمة والإصدار، مثلاً IFoo.Type

يحاول HIDL إكمال الاسم باستخدام قواعد التداخل التلقائي (القاعدة الأدنى الرقم يعني أولوية أعلى).

القاعدة 1

في حال عدم توفير حزمة وإصدار، تتم محاولة البحث عن اسم محلي. مثال:

interface Nfc {
    typedef string NfcErrorMessage;
    send(NfcData d) generates (@1.0::NfcStatus s, NfcErrorMessage m);
};

تم البحث عن NfcErrorMessage محليًا وtypedef فوقه. تم البحث عن NfcData أيضًا محليًا، ولكن كما هو غير محدد محليًا، يتم استخدام القاعدة 2 و3. @1.0::NfcStatus نسخة، لذا لا تنطبق القاعدة 1.

القاعدة 2

في حال فشل القاعدة 1 وفقدان أحد مكونات الاسم المؤهل بالكامل (الحزمة أو الإصدار أو الحزمة والإصدار)، يتم ملء المكون تلقائيًا ومعلومات من الحزمة الحالية. ثم يبحث محول HIDL في الملف الحالي (وجميع عمليات الاستيراد) للعثور على الاسم المؤهّل بالكامل الذي تم ملؤه تلقائيًا. باستخدام المثال أعلاه، يجب افتراض أنّ بيان ExtendedNfcData تم التحويل في نفس الطرد (android.hardware.nfc) الإصدار (1.0) على النحو التالي: NfcData:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

يملأ المحول البرمجي لـ HIDL اسم الحزمة واسم الإصدار من الحزمة الحالية لإنتاج اسم UDT المؤهل بالكامل android.hardware.nfc@1.0::NfcData ونظرًا لأن الاسم موجود في الحزمة الحالية (على افتراض استيرادها بشكل صحيح)، فسيتم استخدامها .

يتم استيراد اسم في الحزمة الحالية فقط إذا كان أي مما يلي: صواب:

  • ويتم استيرادها بشكل صريح باستخدام عبارة import.
  • تم تحديده في types.hal في الحزمة الحالية.

يتم اتباع العملية نفسها إذا كان NfcData مؤهلاً من خلال رقم الإصدار:

struct ExtendedNfcData {
    // autofill the current package name (android.hardware.nfc)
    @1.0::NfcData base;
    // … additional members
};

القاعدة 3

إذا فشلت القاعدة 2 في الحصول على تطابق (لم يتم تحديد UDT في )، يقوم المحول البرمجي HIDL بالبحث عن تطابق ضمن جميع الحزم المستوردة. باستخدام المثال أعلاه، لنفترض أنّه قد تم تعريف السمة ExtendedNfcData في الإصدار 1.1 من الحزمة android.hardware.nfc، تستورد 1.1 1.0 كما يجب (انظر الإضافات على مستوى الحزمة)، والتعريف تحدد فقط اسم UDT:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

يبحث المحول البرمجي عن أي UDT يسمى NfcData ويجد واحدًا في android.hardware.nfc في الإصدار 1.0، ما أدى إلى UDT مؤهلة بالكامل من android.hardware.nfc@1.0::NfcData. إذا كانت أكثر تم العثور على أكثر من مطابقة واحدة لـ UDT مؤهل جزئيًا، وهو برنامج تجميع HIDL إلى حدوث خطأ.

مثال

باستخدام القاعدة 2، يتم تفضيل نوع مستورد محدد في الحزمة الحالية على نوع تم استيراده من حزمة أخرى:

// hardware/interfaces/foo/1.0/types.hal
package android.hardware.foo@1.0;
struct S {};

// hardware/interfaces/foo/1.0/IFooCallback.hal
package android.hardware.foo@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/types.hal
package android.hardware.bar@1.0;
typedef string S;

// hardware/interfaces/bar/1.0/IFooCallback.hal
package android.hardware.bar@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/IBar.hal
package android.hardware.bar@1.0;
import android.hardware.foo@1.0;
interface IBar {
    baz1(S s); // android.hardware.bar@1.0::S
    baz2(IFooCallback s); // android.hardware.foo@1.0::IFooCallback
};
  • يتم استيفاء S كـ android.hardware.bar@1.0::S، وهي متوفرة في bar/1.0/types.hal (لأنّ types.hal يتم تلقائيًا ).
  • يتم استيفاء IFooCallback كـ android.hardware.bar@1.0::IFooCallback باستخدام القاعدة 2، لكنها لا يمكن العثور عليه لأنه لم يتم استيراد bar/1.0/IFooCallback.hal تلقائيًا (كما هو types.hal). وبالتالي، تحل القاعدة 3 android.hardware.foo@1.0::IFooCallback بدلاً من ذلك، والتي تم استيرادها عبر import android.hardware.foo@1.0;).

type.hal

تحتوي كل حزمة HIDL على ملف types.hal يحتوي على أرقام UDT. التي تتم مشاركتها بين جميع الواجهات المشاركة في الحزمة. أنواع HIDL تكون دائمًا عامة؛ بغض النظر عما إذا تم الإعلان عن UDT في types.hal أو ضمن بيان واجهة، تكون هذه الأنواع ويمكن الوصول إليها خارج النطاق الذي تم تعريفها فيه. types.hal لا يعني وصف واجهة برمجة التطبيقات العامة للحزمة، بل لاستضافة لغات UDT تستخدمها جميع الواجهات ضمن الحزمة. نظرًا لطبيعة HIDL، يمكن لجميع تشكل جزءًا من الواجهة.

تتكوّن الدالة types.hal من عبارتَي UDT وimport. بما أنّ types.hal متاحة لكل واجهة من حزمة (استيراد ضمني)، تكون عبارات import هذه على مستوى الحزمة حسب التعريف. يمكن أيضًا أن تتضمّن الأسماء الموجّهة (UDT) في types.hal واجهات UDT والواجهات التي تم استيرادها.

على سبيل المثال، لـ IFoo.hal:

package android.hardware.foo@1.0;
// whole package import
import android.hardware.bar@1.0;
// types only import
import android.hardware.baz@1.0::types;
// partial imports
import android.hardware.qux@1.0::IQux.Quux;
// partial imports
import android.hardware.quuz@1.0::Quuz;

يتم استيراد ما يلي:

  • android.hidl.base@1.0::IBase (ضمنيًا)
  • android.hardware.foo@1.0::types (ضمنيًا)
  • كل شيء في android.hardware.bar@1.0 (بما في ذلك الكل الواجهات وtypes.hal)
  • types.hal من android.hardware.baz@1.0::types (لا يتم استيراد الواجهات في android.hardware.baz@1.0)
  • IQux.hal وtypes.hal من android.hardware.qux@1.0
  • Quuz من android.hardware.quuz@1.0 (بافتراض يتم تحديد Quuz في types.hal، حيث تم تحليل ملف types.hal، ولكن بأنواع أخرى غير Quuz. ).

تحديد الإصدارات على مستوى الواجهة

تكمن كل واجهة ضمن الحزمة في ملفها الخاص. حزمة التي تنتمي إليها هذه الواجهة في أعلى الواجهة باستخدام عبارة package. بعد بيان الحزمة، صفر أو أكثر قد يتم سرد عمليات استيراد على مستوى الواجهة (حزمة جزئية أو كاملة). مثلاً:

package android.hardware.nfc@1.0;

في HIDL، يمكن أن تكتسب الواجهات من الواجهات الأخرى باستخدام كلمة رئيسية واحدة (extends). لكي تقوم الواجهة بتوسيع واجهة أخرى، يجب أن يكون لدى المستخدم إذن بالوصول إليها من خلال عبارة import. اسم الواجهة التي يتم توسيعها (الواجهة الأساسية) يتبع القواعد الخاصة بـ type-name أو مؤهلات الشركة المذكورة أعلاه. لا يجوز أن تكتسِب الواجهة إلّا من واجهة واحدة. لا يدعم HIDL الوراثة المتعددة.

تستخدم أمثلة الترقية أدناه الحزمة التالية:

// types.hal
package android.hardware.example@1.0
struct Foo {
    struct Bar {
        vec<uint32_t> val;
    };
};

// IQuux.hal
package android.hardware.example@1.0
interface IQuux {
    fromFooToBar(Foo f) generates (Foo.Bar b);
}

قواعد Uprev

لتعريف حزمة package@major.minor، تكون إما A أو كل B يجب أن تكون true:

القاعدة أ "هو إصدار ثانوي للبداية": جميع الإصدارات الثانوية السابقة "package@major.0" و"package@major.1" و...، يجب عدم تحديد package@major.(minor-1).
أو
القاعدة "ب"

ينطبق كل ما يلي:

  1. "النسخة الثانوية السابقة صالحة": package@major.(minor-1) وأن يتبع نفس القاعدة A (لا ينطبق أي من من package@major.0 إلى package@major.(minor-2) ) أو القاعدة B (إذا كانت قيمة أعلى من @major.(minor-2))

    وأيضًا

  2. "اكتساب واجهة واحدة على الأقل بالاسم نفسه": هناك الواجهة package@major.minor::IFoo التي تمتد package@major.(minor-1)::IFoo (إذا كانت الحزمة السابقة لها واجهة)

    وأيضًا

  3. "لا توجد واجهة مكتسبة باسم مختلف": يجب ألا تكون موجودة package@major.minor::IBar يمتد package@major.(minor-1)::IBaz، حيث يمكن لـ IBar IBaz هما اسمان مختلفان. إذا كانت هناك واجهة بها الاسم نفسه، يجب تمديد package@major.minor::IBar package@major.(minor-k)::IBar بحيث لا يوجد أي بار (IBar) مع أصغر k.

بسبب القاعدة "أ":

  • يمكن أن تبدأ الحزمة بأي رقم إصدار ثانوي (على سبيل المثال، android.hardware.biometrics.fingerprint يبدأ في @2.1).
  • الشرط "android.hardware.foo@1.0 غير محدّد" يعني فيجب ألا يكون الدليل hardware/interfaces/foo/1.0 موجودًا أصلاً.

ومع ذلك، لا تؤثر القاعدة A على حزمة لها نفس اسم الحزمة ولكن إصدار رئيسي مختلف (على سبيل المثال، android.hardware.camera.device تحتوي على كل من @1.0 تم تحديد @3.2؛ لا يحتاج "@3.2" إلى التفاعل مع. @1.0.) وبالتالي، يمكن لـ @3.2::IExtFoo تمديد @1.0::IFoo

شريطة أن يكون اسم الحزمة مختلفًا، يمكن توسيع نطاق package@major.minor::IBar من واجهة ذات اسم مختلف (على سبيل المثال، android.hardware.bar@1.0::IBar يمكن التمديد android.hardware.baz@2.2::IBaz). إذا لم تكن هناك واجهة أن تعلن بشكلٍ صريح عن نوع فائق باستخدام الكلمة الرئيسية extend، فإنه يمتد إلى android.hidl.base@1.0::IBase (باستثناء IBase نفسها).

يجب اتباع B.2 وB.3 في نفس الوقت. على سبيل المثال، حتى إذا تمديدات "android.hardware.foo@1.1::IFoo" android.hardware.foo@1.0::IFoo لتمرير القاعدة B.2، إذا كانت امتداد android.hardware.foo@1.1::IExtBar android.hardware.foo@1.0::IBar، لا تزال هذه الزيادة غير صالحة.

واجهات Uprev

لرفع قيمة android.hardware.example@1.0 (الموضحة أعلاه) إلى @1.1:

// types.hal
package android.hardware.example@1.1;
import android.hardware.example@1.0;

// IQuux.hal
package android.hardware.example@1.1
interface IQuux extends @1.0::IQuux {
    fromBarToFoo(Foo.Bar b) generates (Foo f);
}

هذا import على مستوى الحزمة من الإصدار "1.0" من android.hardware.example في types.hal. بدون إضافة معلومات جديدة تمت إضافة الأحرف UDT في الإصدار 1.1 من الحزمة، ويشير هذا المصطلح إلى الأحرف UDT في لا تزال هناك حاجة إلى الإصدار 1.0، وبالتالي يجب إجراء الاستيراد على مستوى الحزمة في types.hal. (كان من الممكن تحقيق نفس التأثير باستخدام استيراد على مستوى الواجهة في IQuux.hal).

في extends @1.0::IQuux في بيان IQuux، حدّدنا إصدار IQuux الذي يجري استخدامه مكتسب (يجب توضيح الغموض نظرًا لاستخدام IQuux إعلان واجهة واكتسابها من واجهة). نظرًا لأن التعريفات هي أسماءً تكتسب جميع سمات الحزمة والإصدار على موقع الويب يجب أن يكون التوضيح في اسم الواجهة الأساسية. نحن كان بإمكان المستخدم استخدام لغة UDT المؤهلة بالكامل أيضًا، ولكن كان من الممكن متكرر.

لم تعرض الواجهة الجديدة IQuux طريقة إعادة تعريف fromFooToBar() المكتسَب من @1.0::IQuux ببساطة الطريقة الجديدة التي تتم إضافتها fromBarToFoo(). مُكتسَب في HIDL لا يمكن تعريفها مرة أخرى في الواجهات الفرعية، لذا لا يمكن لواجهة IQuux الإعلان عن fromFooToBar() بشكل صريح.

اصطلاحات Uprev

في بعض الأحيان، يجب أن تعيد أسماء الواجهات تسمية الواجهة الموسّعة. ننصحك بما يلي: أن إضافات التعداد والتركيبات والاتحادات تحمل الاسم نفسه الذي تُوسِّعه ما لم تكن مختلفة بما يكفي لتبرير اسم جديد. أمثلة:

// in parent hal file
enum Brightness : uint32_t { NONE, WHITE };

// in child hal file extending the existing set with additional similar values
enum Brightness : @1.0::Brightness { AUTOMATIC };

// extending the existing set with values that require a new, more descriptive name:
enum Color : @1.0::Brightness { HW_GREEN, RAINBOW };

فإذا كان لإحدى الطرق اسم دلالي جديد (على سبيل المثال، fooWithLocation) إذًا هو الخيار المفضّل. بخلاف ذلك، يجب أن يكون على غرار ما يمده. على سبيل المثال، الطريقة يمكن استخدام foo_1_1 في @1.1::IFoo بدلاً من الوظيفة من طريقة foo في @1.0::IFoo إذا لم تكن هناك طريقة اسم بديل.

تحديد الإصدارات على مستوى الحزمة

يحدث إصدار HIDL على مستوى الحزمة؛ بعد نشر الحزمة، فإنه غير قابل للتغيير (لا يمكن تغيير مجموعة واجهاته ولا يمكن تغيير UDT). يمكن للحزم وترتبط ببعضها البعض بعدة طرق، وكلها يمكن التعبير عنها من خلال الجمع بين التوريث على مستوى الواجهة وإنشاء معرّفات UDT حسب التركيب.

ومع ذلك، هناك نوع واحد من العلاقات محدد بدقة ويجب تنفيذه: اكتساب متوافق مع الإصدارات القديمة على مستوى الحزمة: في هذا السيناريو، الحزمة parent هي الحزمة التي يتم اكتسابها منها حزمة child هي التي تُوسّع نطاق العنصر الرئيسي. على مستوى الحزمة تكون قواعد الاكتساب المتوافقة مع الإصدارات القديمة على النحو التالي:

  1. يتم اكتساب جميع واجهات المستوى الأعلى للحزمة الرئيسية من الواجهات في حزمة فرعية.
  2. يمكن أيضًا إضافة الواجهات الجديدة إلى الحزمة الجديدة (لا توجد قيود حول العلاقات بالواجهات الأخرى في الحزم الأخرى).
  3. يمكن أيضًا إضافة أنواع بيانات جديدة لاستخدامها من خلال أي من الطريقتين الجديدتين لتحسين الأداء. الواجهات الحالية أو حسب الواجهات الجديدة.

يمكن تنفيذ هذه القواعد باستخدام الاكتساب على مستوى واجهة HIDL لكنّها تتطلب معرفة على مستوى البيانات الوصفية للتعرّف على هذه العلاقات لتشكيل امتداد حزمة متوافق مع الإصدارات القديمة. يتم استنتاج هذه المعلومات. على النحو التالي:

في حال استيفاء الحزمة هذا الشرط، يتم فرض سياسة hidl-gen. قواعد التوافق مع الأنظمة القديمة.