أنواع البيانات

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

بما أنّ وقت تشغيل Java لا يتيح استخدام الأعداد الصحيحة غير الموقَّعة بشكلٍ تلقائي، تتم معالجة جميع الأنواع غير الموقَّعة (والقوائم المحدَّدة المستندة إليها) تلقائيًا على أنّها الأنواع الموقَّعة المماثلة لها، أي أنّ uint32_t تصبح int في واجهة Java. لا يتم إجراء أي تحويل للقيمة، ويجب أن يستخدم منفّذ الإجراء على جانب Java القيم الموقَّعة كما لو لم تكن موقَّعة.

تعدادات

لا تُنشئ قوائم التعداد فئات Java، ولكن يتم ترجمتها بدلاً من ذلك إلى فئات داخلية تحتوي على تعريف ثابت ثابت لكل حالة من حالات التعداد. إذا كانت فئة enum مشتقة من فئة enum أخرى، فإنّها ترث نوع تخزين تلك الفئة. تتم إعادة كتابة التعدادات المستندة إلى نوع عدد صحيح غير موقَّع إلى القيمة المقابلة لها الموقَّعة. بما أنّ النوع الأساسي هو نوع أساسي، تكون القيمة التلقائية لسمات/متغيّرات التعداد هي صفر حتى في حال عدم توفّر معرّف عدد صحيح موجب.

على سبيل المثال، 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 دعمًا لأنواع handle و memory في Java. وتمّت ترجمتها إلى android.os.NativeHandle و android.os.HidlMemory، على التوالي. يُعتبر الاسم المعرِّف غير المحدَّد صالحًا، في حين أنّ ذاكرة غير المحدَّدة غير صالحة.

في رمز الخادم الذي تم إنشاؤه، تكون وسيطات الذاكرة والاسم المعرِّف التي تم استلامها صالحة فقط ضمن نطاق استدعاء الطريقة. إذا أراد فريق تنفيذ الخادم تمديد فترة صلاحيتها، يجب تكرارها باستخدام طرق dup() الخاصة بها. يمكن استخدام المثيل الذي تم إرجاعه بعد انتهاء استدعاء الطريقة، ويجب إغلاقه بشكل صحيح عند الانتهاء من استخدامه.

في رمز العميل الذي تم إنشاؤه، لا يلزم تكرار الأسماء المعرِّفة ومثيلات الذاكرة التي يتم إرسالها كوسيطات إدخال للطريقة التي يتمّ استدعاؤها، ولا يلزم إبقاؤها صالحة بعد انتهاء الطريقة. ومع ذلك، فإنّ الأسماء المعرِّفة ومثيلات الذاكرة التي يتم تلقّيها كوسيطات إخراج يتم تكرارها تلقائيًا من خلال الرمز المُنشئ تلقائيًا ويجب إغلاقها بشكل صحيح عند الانتهاء منها. وينطبق ذلك سواء كانت دلابلا param التي يتم إرجاعها تظهر كقيم إرجاع للطريقة (في حالة القيمة المفردة التي يتم إرجاعها) أو باستخدام أسلوب callback المتزامن (الذي يتم استخدامه في حالة القيم المتعدّدة التي يتم إرجاعها).

لمزيد من المعلومات عن التكرار والإغلاق، اطّلِع على مستندات فئات 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).