HIDL جافا

في Android 8.0 ، تمت إعادة تصميم نظام التشغيل Android لتحديد واجهات واضحة بين نظام Android المستقل عن الجهاز ، والرمز الخاص بالجهاز والبائع. قام Android بالفعل بتعريف العديد من هذه الواجهات في شكل واجهات HAL ، والتي تم تعريفها على أنها رؤوس C في hardware/libhardware . استبدلت HIDL واجهات HAL هذه بواجهات مستقرة ذات إصدار ، والتي يمكن أن تكون إما في Java (الموضحة أدناه) أو تكون واجهات 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 من JARs المخصصة المثبتة على الجهاز مع Java APIs الثابتة المتاحة باستخدام آلية uses-library الحالية لتطبيقات النظام. النهج الأخير يوفر مساحة على الجهاز. لمزيد من التفاصيل ، راجع تنفيذ مكتبة Java 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 ، ويجب أن يكون للتطبيقات التي تستخدم هذه (التطبيقات الخاصة بالضرورة) نسخ منفصلة خاصة بها. يجب أن تستخدم الوحدات النمطية في مسار فئة التمهيد باستخدام HIDL المتغيرات السطحية لمكتبات Java هذه ولإضافة jarjar_rules: ":framework-jarjar-rules" إلى Android.bp بها لاستخدام إصدار هذه المكتبات الموجود في مسار فئة التمهيد.

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

هناك إصدار واحد فقط ( @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 ، يمكنك تنفيذ واجهتك في Java باستخدام الخطوات التالية:

  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 الملف hardware/interfaces/foo/1.0/IFooCallback.hal ، يُنشئ هذا الملف /tmp/android/hardware/foo/1.0/IFooCallback.java ، والذي يغلف واجهة Java ورمز الوكيل /tmp/android/hardware/foo/1.0/IFooCallback.java (كلاهما الوكيل والأوتاد تتوافق مع الواجهة).

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

تشغيل الخدمة

يوفر HAL واجهة IFoo ، والتي يجب أن تقوم بعمليات رد IFooCallback غير متزامنة إلى إطار العمل عبر واجهة 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 امتداد الواجهة IBetterFoo ، على النحو التالي:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

يمكن أن يستخدم كود الاتصال المدرك للواجهة الممتدة طريقة Java 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.
}