عند توفّر ملف واجهة HIDL، تنشئ الخلفية Java HIDL واجهات Java ورمزَي Stub وProxy. وهي تتيح جميع أنواع HIDL العددية
([u]int{8,16,32,64}_t, float, double, و
enums)، بالإضافة إلى السلاسل النصية والواجهات وأنواع safe_union وأنواع البنية
والمصفوفات والمتجهات من أنواع HIDL المتوافقة. لا تتيح الخلفية Java HIDL أنواع union أو أنواع 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.
النوعان handle وmemory
يتيح Android 11 إمكانية استخدام النوعَين handle و
memory في Java. ويتم تحويلهما إلى 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).