عند توفّر ملف واجهة HIDL، ينشئ برنامج Java HIDL الخلفي واجهات Java ورمز Stub وProxy. يتوافق مع جميع أنواع HIDL العددية
([u
]int
{8,16,32,64}_t, float, double,
و
enum
)، بالإضافة إلى السلاسل والواجهات وأنواع safe_union وأنواع struct
والمصفوفات والمتجهات لأنواع HIDL المتوافقة. لا يتيح برنامج Java HIDL الخلفي أنواع الاتحاد أو أنواع fmq. يتيح نظام التشغيل Android 11 استخدام النوعَين memory
وhandle
.
بما أنّ وقت تشغيل Java لا يتيح استخدام الأعداد الصحيحة غير الموقّعة بشكلٍ أصلي، يتم التعامل مع جميع الأنواع غير الموقّعة (والتعدادات المستندة إليها) على أنّها الأنواع الموقّعة المكافئة لها، أي أنّ uint32_t
يصبح int
في واجهة Java. لا يتم إجراء أي تحويل للقيمة، ويجب أن يستخدم المنفّذ على جانب Java القيم الموقّعة كما لو كانت غير موقّعة.
تعدادات
لا تنشئ التعدادات فئات تعداد Java، ولكن يتم بدلاً من ذلك ترجمتها إلى فئات داخلية تحتوي على تعريف ثابت لكل حالة تعداد. إذا كان صف تعداد مشتقًا من صف تعداد آخر، سيرث نوع التخزين الخاص بهذا الصف. تتم إعادة كتابة التعدادات المستندة إلى نوع عدد صحيح غير موقّع إلى ما يعادلها من أعداد صحيحة موقّعة. بما أنّ النوع الأساسي هو نوع أولي، تكون القيمة التلقائية لحقول/متغيرات التعداد صفرًا حتى في حال عدم توفّر تعداد صفر.
على سبيل المثال، SomeBaseEnum
من النوع uint8_t
:
enum SomeBaseEnum : uint8_t { foo = 3 }; enum SomeEnum : SomeBaseEnum { quux = 33, goober = 127 };
… يصبح:
public final class SomeBaseEnum { public static final byte foo = 3; } public final class SomeEnum { public static final byte foo = 3; public static final byte quux = 33; public static final byte goober = 127; }
و:
enum SomeEnum : uint8_t { FIRST_CASE = 10, SECOND_CASE = 192 };
… تتم إعادة كتابتها على النحو التالي:
public final class SomeEnum { static public final byte FIRST_CASE = 10; // no change static public final byte SECOND_CASE = -64; }
آلات وترية
يكون نوع String
في Java هو utf-8 أو utf-16، ولكن يتم تحويله إلى utf-8
كنوع HIDL الشائع عند نقله. بالإضافة إلى ذلك، يجب ألا تكون قيمة String
فارغة عند تمريرها إلى HIDL.
المقبض والذاكرة
يوفّر نظام التشغيل Android 11 إمكانية استخدام Java مع النوعَين handle
وmemory
. وتتم ترجمتها إلى android.os.NativeHandle
وandroid.os.HidlMemory
على التوالي. يُعتبر المؤشر الفارغ صالحًا، بينما لا تُعتبر الذاكرة الفارغة صالحة.
في رمز الخادم الذي تم إنشاؤه، تكون وسيطات الذاكرة والمقابض التي تم تلقّيها صالحة فقط ضمن نطاق استدعاء الطريقة. إذا أراد تنفيذ الخادم تمديد مدة صلاحيته، يجب تكراره باستخدام طرق dup()
الخاصة به. يمكن استخدام النسخة التي تم إرجاعها بعد استدعاء الطريقة، ويجب إغلاقها بشكل صحيح عند الانتهاء من استخدامها.
في رمز العميل الذي تم إنشاؤه، لا يلزم تكرار المقابض ومثيلات الذاكرة التي يتم إرسالها كمعلمات إدخال للطريقة التي تم استدعاؤها، كما لا يلزم إبقاؤها صالحة بعد أن تعرض الطريقة النتيجة. ومع ذلك، يتم تلقائيًا تكرار المقابض ومثيلات الذاكرة التي يتم تلقّيها كمعلمات إخراج بواسطة الرمز البرمجي الذي يتم إنشاؤه تلقائيًا، ويجب إغلاقها بشكل صحيح عند الانتهاء من استخدامها. وينطبق ذلك سواء ظهرت وسيطات الإرجاع كقيم إرجاع للطريقة (في حالة قيمة الإرجاع الفردية) أو باستخدام نمط معاودة الاتصال المتزامن (المستخدَم في حالة قيمة الإرجاع المتعددة).
لمزيد من المعلومات حول التكرار والإغلاق، يُرجى الاطّلاع على مستندات فئات Java.
المصفوفات والمتجهات
يتم تحويل المصفوفات إلى مصفوفات Java، ويتم تحويل المتجهات إلى
ArrayList<T>
حيث T هو نوع الكائن المناسب، وربما
يتم تضمين أنواع قياسية مثل vec<int32_t> =>
ArrayList<Integer>
). على سبيل المثال:
takeAnArray(int32_t[3] array); returnAVector() generates (vec<int32_t> result);
… يصبح:
void takeAnArray(int[] array); ArrayList<Integer> returnAVector();
البُنى
تتم ترجمة البِنى إلى فئات Java بتنسيق مشابه. على سبيل المثال:
struct Bar { vec<bool> someBools; }; struct Foo { int32_t a; int8_t b; float[10] c; Bar d; };
… يصبح:
class Bar { public final ArrayList<Boolean> someBools = new ArrayList(); }; class Foo { public int a; public byte b; public final float[] c = new float[10]; public final Bar d = new Bar(); }
الأنواع المُعلَن عنها
يحصل كل نوع من الأنواع ذات المستوى الأعلى التي تم تعريفها في types.hal
على ملف إخراج .java خاص به (كما هو مطلوب في Java). على سبيل المثال، يؤدي الملف التالي
types.hal
إلى إنشاء ملفَين إضافيَّين (Foo.java
وBar.java):
struct Foo { ... }; struct Bar { ... struct Baz { }; ... };
يتم تحديد Baz في فئة داخلية ثابتة من Bar (في Bar.java
).