لغة HIDL Java

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

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

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

مثال على العميل

هذا مثال على أحد البرامج للواجهة IFoo في الحزمة android.hardware.foo@1.0 المسجّلة كاسم للخدمة default وخدمة إضافية باسم الخدمة المخصّصة second_impl

إضافة مكتبات

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

// 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

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

بدءًا من Android 10، "shallow" نُسخًا من هذه المكتبات تتوفر أيضًا. وتشمل هذه الفئة الفئة المعنية ولكنها لا تتضمن أي الفئات التابعة. على سبيل المثال: يتضمن android.hardware.foo-V1.0-java-shallow فئات في foo. على الإنترنت، لكنه لا يتضمن الفئات في 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 الأساسية والمديرة متوفّرة أيضًا عند التشغيل. classpath للتطبيقات (كانت تُستخدَم سابقًا كواجهة برمجة تطبيقات مخفية، بسبب برنامج تحميل الفئة الأولى المفوَّض في Android). وبدلاً من ذلك، تم نقلهم إلى مساحة الاسم مع jarjar، والتطبيقات التي تستخدم هذه (بالضرورة خاصة) التطبيقات) على نُسخ منفصلة خاصة بها. الوحدات في مسار التمهيد باستخدام يجب أن يستخدم HIDL المتغيرات السطحية لمكتبات Java هذه، وأن تضيف في jarjar_rules: ":framework-jarjar-rules" Android.bp لاستخدام نسخة هذه المكتبات المتوفّرة في مسار فئة التمهيد.

تعديل مصدر Java

هناك إصدار واحد فقط (@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، يؤدي هذا إلى إنشاء الملف /tmp/android/hardware/foo/1.0/IFooCallback.java، الذي تغليف واجهة Java، وكود الوكيل، والأجزاء البديلة (كل من الخادم الوكيل الرموز البديلة مع الواجهة).

ينشئ -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() طريقة Java لإرسال الواجهة الأساسية إلى الواجهة الموسعة:

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.
}