در اندروید 8.0 سیستم عامل اندروید مجدداً طراحی شد تا رابط های واضحی بین پلتفرم اندروید مستقل از دستگاه و کدهای دستگاه و فروشنده مشخص شود. اندروید قبلاً بسیاری از این رابطها را در قالب رابطهای HAL تعریف کرده است که به عنوان هدر C در hardware/libhardware
تعریف میشود. HIDL این رابطهای HAL را با اینترفیسهای نسخهدار و پایدار جایگزین کرد، که میتوانند در جاوا (توضیح داده شده در زیر) یا رابطهای HIDL سمت سرویس گیرنده و سرور در C++ باشند.
اینترفیسهای HIDL عمدتاً از کدهای بومی استفاده میشوند و در نتیجه HIDL بر تولید خودکار کد کارآمد در C++ متمرکز است. با این حال، رابط های HIDL نیز باید برای استفاده مستقیم از جاوا در دسترس باشند، زیرا برخی از زیرسیستم های اندروید (مانند تلفن) دارای رابط های Java HIDL هستند.
صفحات این بخش پیشانی جاوا را برای رابطهای HIDL شرح میدهند، نحوه ایجاد، ثبت و استفاده از خدمات را توضیح میدهند و نحوه تعامل HAL و کلاینتهای HAL نوشته شده در جاوا را با سیستم 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
ملاحظات اضافی برای افزودن کتابخانه ها در اندروید 10
اگر سیستم یا برنامه فروشنده ای دارید که Android 10 یا بالاتر را هدف قرار می دهد، می توانید این کتابخانه ها را به صورت ایستا اضافه کنید. همچنین میتوانید از کلاسهای HIDL (فقط) از JARهای سفارشی نصبشده روی دستگاه با رابطهای برنامهنویسی برنامهنویسی نرمافزار جاوا پایدار که با استفاده از مکانیزم uses-library
موجود برای برنامههای سیستم در دسترس هستند، استفاده کنید. روش دوم باعث صرفه جویی در فضا در دستگاه می شود. برای جزئیات بیشتر، به اجرای کتابخانه Java SDK مراجعه کنید. برای برنامه های قدیمی تر، رفتار قدیمی حفظ می شود.
با شروع اندروید 10، نسخههای کم عمق این کتابخانهها نیز در دسترس هستند. اینها شامل کلاس مورد نظر می شود اما هیچ یک از کلاس های وابسته را شامل نمی شود. برای مثال، 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 نیز دیگر در مسیر کلاس راهاندازی برای برنامهها در دسترس نیستند (پیش از این، به دلیل بارگزاری کلاس اول Android از آنها به عنوان API پنهان استفاده میشدند). در عوض، آنها به یک فضای نام جدید با jarjar
منتقل شدهاند و برنامههایی که از اینها استفاده میکنند (الزاماً برنامههای خصوصی) باید کپیهای جداگانه خود را داشته باشند. ماژولهای موجود در مسیر کلاس بوت با استفاده از HIDL باید از انواع کم عمق این کتابخانههای جاوا استفاده کنند و 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(…);
خدمات ارائه دهد
کد فریم ورک در جاوا ممکن است برای دریافت تماس های ناهمزمان از HAL ها به رابط ها نیاز داشته باشد.
برای رابط IFooCallback
در نسخه 1.0 بسته android.hardware.foo
، می توانید با استفاده از مراحل زیر رابط خود را در جاوا پیاده سازی کنید:
- رابط کاربری خود را در HIDL تعریف کنید.
-
/tmp/android/hardware/foo/IFooCallback.java
را به عنوان مرجع باز کنید. - یک ماژول جدید برای پیاده سازی جاوا خود ایجاد کنید.
- کلاس انتزاعی
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
را تولید میکند که رابط جاوا، کد پراکسی، و خردهها (هر دو پراکسی) را در بر میگیرد. و خرد مطابق با رابط).
-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. }