HIDL جافا

في Android 8.0 ، تمت إعادة تصميم نظام التشغيل Android لتحديد واجهات واضحة بين نظام Android المستقل عن الجهاز ، والرمز الخاص بالجهاز والبائع. الروبوت محددة بالفعل العديد من هذه الواجهات في شكل واجهات HAL، الذي يعرف بأنه رؤوس C في hardware/libhardware . استبدال HIDL هذه الواجهات HAL مع مستقرة، واجهات إصداراتها، والتي يمكن أن تكون إما في جافا (هو موضح أدناه) أو يكون client- ومن جانب الخادم واجهات HIDL في C ++ .

تهدف واجهات HIDL إلى استخدامها بشكل أساسي من الكود الأصلي ، ونتيجة لذلك تركز HIDL على التوليد التلقائي للكود الفعال في C ++. ومع ذلك ، يجب أن تكون واجهات HIDL متاحة أيضًا للاستخدام مباشرة من Java ، حيث أن بعض أنظمة Android الفرعية (مثل Telephony) بها واجهات Java HIDL.

تصف الصفحات في هذا القسم الواجهة الأمامية لـ Java لواجهات HIDL ، وتفاصيل كيفية إنشاء الخدمات وتسجيلها واستخدامها ، وتشرح كيفية تفاعل عملاء HALs و HAL المكتوبون في Java مع نظام HIDL RPC.

كونك عميل

وهذا مثال من عميل لواجهة IFoo في حزمة android.hardware.foo@1.0 التي تم تسجيلها مثل اسم الخدمة default وخدمة إضافية مع العرف اسم الخدمة second_impl .

إضافة مكتبات

تحتاج إلى إضافة التبعيات على مكتبة HIDL stub المقابلة إذا كنت تريد استخدامها. عادة ، هذه مكتبة ثابتة:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

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

// in Android.bp
libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

اعتبارات إضافية لإضافة مكتبات في Android 10

إذا كان لديك نظام أو تطبيق بائع يستهدف Android 10 أو أعلى ، فيمكنك تضمين هذه المكتبات بشكل ثابت. يمكنك أيضا استخدام (فقط) الطبقات HIDL من الجرار المخصصة المثبتة على الجهاز مع مستقرة جافا واجهات برمجة التطبيقات توفيرها باستخدام القائمة uses-library آلية لتطبيقات النظام. النهج الأخير يوفر مساحة على الجهاز. لمزيد من التفاصيل، انظر تطبيق جافا مكتبة SDK . بالنسبة للتطبيقات القديمة ، يتم الاحتفاظ بالسلوك القديم.

بدءًا من Android 10 ، تتوفر أيضًا إصدارات "ضحلة" من هذه المكتبات. وتشمل هذه الفئة المعنية ولكنها لا تشمل أيًا من الفئات التابعة. على سبيل المثال، android.hardware.foo-V1.0-java-shallow يشمل الفئات في حزمة فو، ولكن لا يشمل دروسا في android.hidl.base-V1.0-java ، والذي يحتوي على الفئة الأساسية من كل HIDL واجهات. إذا كنت تقوم بإنشاء مكتبة تحتوي بالفعل على الفئات الأساسية للواجهة المفضلة المتاحة كتبعية ، فيمكنك استخدام ما يلي:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java-shallow", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow

لم تعد مكتبات قاعدة HIDL والمدير متوفرة أيضًا في مسار فئة التمهيد للتطبيقات (في السابق ، كانت تُستخدم أحيانًا كواجهة برمجة تطبيقات مخفية ، بسبب أداة تحميل فئة المفوض الأول في Android). بدلا من ذلك، لقد تم نقل في مساحة اسم جديد مع jarjar ، والتطبيقات التي تستخدم هذه (التطبيقات PRIV بالضرورة) يجب أن يكون نسخ منفصلة خاصة بهم. وحدات على CLASSPATH التمهيد باستخدام HIDL يجب استخدام الضحلة المتغيرات من هذه المكتبات جافا وإضافة jarjar_rules: ":framework-jarjar-rules" لمن Android.bp لاستخدام نسخة من هذه المكتبات الموجودة في classpath التمهيد.

تعديل مصدر جافا الخاص بك

هناك نسخة واحدة فقط ( @1.0 ) من هذه الخدمة، لذلك هذا الرمز يسترجع فقط هذا الإصدار. انظر ملحقات واجهة لكيفية التعامل مع عدة إصدارات مختلفة من الخدمة.

import android.hardware.foo.V1_0.IFoo;
...
// retry to wait until the service starts up if it is in the manifest
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IFoo anotherServer = IFoo.getService("second_impl", true /* retry */);
server.doSomething(…);

تقديم خدمة

قد تحتاج التعليمات البرمجية الإطارية في Java إلى خدمة واجهات لتلقي عمليات الاسترجاعات غير المتزامنة من HALs.

ل IFooCallback اجهة في الإصدار 1.0 من android.hardware.foo الحزمة، يمكنك تنفيذ واجهتك في جاوة باستخدام الخطوات التالية:

  1. حدد واجهتك في HIDL.
  2. مفتوحة /tmp/android/hardware/foo/IFooCallback.java كمرجع.
  3. قم بإنشاء وحدة نمطية جديدة لتنفيذ Java الخاص بك.
  4. دراسة فئة مجردة android.hardware.foo.V1_0.IFooCallback.Stub ، ثم كتابة فئة جديدة لتوسيع نطاقه وتطبيق أساليب مجردة.

عرض الملفات التي تم إنشاؤها تلقائيًا

لعرض الملفات التي تم إنشاؤها تلقائيًا ، قم بتشغيل:

hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0

هذه الأوامر توليد الدليل /tmp/android/hardware/foo/1.0 . لملف hardware/interfaces/foo/1.0/IFooCallback.hal ، وهذا يولد ملف /tmp/android/hardware/foo/1.0/IFooCallback.java ، التي بتغليف واجهة جافا، رمز بالوكالة، وبذرة (على حد سواء وكيل و stubs متوافق مع الواجهة).

-Lmakefile يولد القواعد التي بتشغيل هذا الأمر في وقت الإنشاء، ويسمح لك لتشمل android.hardware.foo-V1.0-java وصلة ضد الملفات المناسبة. برنامج نصي تلقائيا يفعل هذا لمشروع كامل من واجهات ويمكن الاطلاع على hardware/interfaces/update-makefiles.sh . المسارات في هذا المثال نسبية ؛ يمكن أن تكون الأجهزة / الواجهات دليلًا مؤقتًا ضمن شجرة التعليمات البرمجية الخاصة بك لتمكينك من تطوير HAL قبل نشره.

تشغيل الخدمة

يوفر HAL لل IFoo اجهة، والتي يجب جعل الاستدعاء غير متزامن إلى إطار على IFooCallback اجهة. و IFooCallback لم يتم تسجيل واجهة بالاسم كخدمة اكتشافها. بدلا من ذلك، IFoo يجب أن يحتوي على طريقة مثل setFooCallback(IFooCallback x) .

لإعداد IFooCallback من الإصدار 1.0 من android.hardware.foo الحزمة، إضافة android.hardware.foo-V1.0-java ل Android.mk . الكود لتشغيل الخدمة هو:

import android.hardware.foo.V1_0.IFoo;
import android.hardware.foo.V1_0.IFooCallback.Stub;
....
class FooCallback extends IFooCallback.Stub {
    // implement methods
}
....
// Get the service from which you will be receiving callbacks.
// This also starts the threadpool for your callback service.
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
....
// This must be a persistent instance variable, not local,
//   to avoid premature garbage collection.
FooCallback mFooCallback = new FooCallback();
....
// Do this once to create the callback service and tell the "foo-bar" service
server.setFooCallback(mFooCallback);

ملحقات الواجهة

على افتراض معين تنفذ خدمة IFoo اجهة عبر جميع الأجهزة، فمن الممكن أن على جهاز معين خدمة قد توفر قدرات إضافية تنفيذها في ملحق واجهة IBetterFoo ، على النحو التالي:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

كود الاتصال على بينة من واجهة طويلة يمكن استخدام castFrom() طريقة جافا للادلاء بأمان واجهة القاعدة إلى واجهة طويلة:

IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IBetterFoo extendedService = IBetterFoo.castFrom(baseService);
if (extendedService != null) {
  // The service implements the extended interface.
} else {
  // The service implements only the base interface.
}