في Android 11 والإصدارات الأحدث، يمكن تشغيل خدمات AIDL الأصلية التي تعمل في قسم النظام وإيقافها ديناميكيًا حسب الحاجة. تبدأ الخدمات الديناميكية عند طلبها لأول مرة وتتوقف تلقائيًا عندما لا يعود هناك حاجة إليها.
الخدمات التي يمكن تشغيلها ديناميكيًا
لا تتوفّر هذه الميزة إلا للخدمات الأصلية التي يمكن التحكّم في دورات حياتها من خلال init وservicemanager. لا تتوافق هذه الميزة مع الخدمات ضمن حِزم التطبيقات، ويجب استخدام الخدمات المرتبطة بدلاً منها.
يعمل الإيقاف الديناميكي من خلال إيقاف العملية التي تعمل فيها الخدمة. إذا كانت هناك عدة خدمات في العملية نفسها، يجب تسجيلها جميعًا كخدمات ديناميكية لتكون متوافقة مع هذه الميزة. بعد ذلك، سيتم إيقاف هذه العملية عندما لا يعود هناك حاجة إلى أي من الخدمات.
ضبط ملف init .rc لخدمة
لتشغيل خدمة ديناميكيًا، أضِف الخيارات التالية إلى ملف init
.rc للخدمة بعد السطر الأول service <name> <cmd>
interface aidl serviceName
disabled
oneshot
تنفّذ هذه الخيارات ما يلي:
interface aidl serviceName: يسمح لـservicemanagerبالعثور على الخدمة. إذا كانت الخدمة تستخدم واجهات متعددة، عليك تعريف كل واجهة على سطر منفصل. يجب أن تكون هذه الأسماء مطابقة تمامًا لما يتوقّعهservicemanagerوقد تختلف عن اسم العملية.disabled: يمنع بدء الخدمة تلقائيًا عند التشغيل.oneshot: يمنع إعادة تشغيل الخدمة تلقائيًا في كل مرة يتم إيقافها.
لمزيد من المعلومات، يُرجى الاطّلاع على ملف Android Init Language Readme في AOSP.
أمثلة:
تسجيل خدمة
يتم إنشاء كل خدمة وتسجيلها في servicemanager. يتم التسجيل غالبًا في ملف باسم main.cpp، ولكن يمكن أن يختلف التنفيذ. عادةً ما يكون التسجيل على النحو التالي:
using android::defaultServiceManager;
defaultServiceManager()->addService(serviceName, service);
يتم أحيانًا تجريد عملية التسجيل من خلال BinderService::publish أو BinderService::instantiate، اللذَين يستدعيان الرمز أعلاه.
لتسجيل خدمة كخدمة ديناميكية، استبدِل رمز التسجيل بالرمز التالي:
#include <binder/LazyServiceRegistrar.h>
using android::binder::LazyServiceRegistrar;
auto lazyRegistrar = LazyServiceRegistrar::getInstance();
lazyRegistrar.registerService(service, serviceName);
يتواصل servicemanager مع LazyServiceRegistrar لإيقاف الخدمات استنادًا إلى أعداد المراجع.
أمثلة:
ضبط عملاء خدمة AIDL
الحصول على الخدمة
لاسترداد خدمة غير نشطة، يجب بدء الخدمة ثم استردادها.
سيؤدي استدعاء getService في مدير الخدمة إلى بدء الخدمة، ولكن عادةً ما تريد الحصول على الخدمة بمجرد توفّرها، لذا يجب استخدام متغيرات waitForService. يُرجى الاطّلاع على المستندات الخاصة بالواجهة الخلفية لمعرفة كيفية استخدام هذه المتغيرات.
إيقاف الخدمة
يستند الإيقاف الديناميكي إلى عدد المراجع، لذا يجب ألا يحتفظ العملاء بالخدمة عندما لا تكون قيد الاستخدام.
أمثلة:
إيقاف الإيقاف مؤقتًا
إذا أردت تشغيل خدمة بشكل مستقل إلى أن تكتمل مهام معيّنة ثم التبديل إلى السلوك الديناميكي، يمكنك استخدام LazyServiceRegistrar::forcePersist لتفعيل الإيقاف الديناميكي وإيقافه. إذا تم استدعاء هذه الطريقة من جهة الخادم، يجب استدعاؤها قبل registerService.
مثال: apexservice