تشغيل خدمات AIDL ديناميكيًا

بدءًا من نظام التشغيل Android 11، يمكن بدء تشغيل خدمات AIDL الأصلية التي تعمل في قسم النظام وإيقافها ديناميكيًا حسب الحاجة. تبدأ الخدمات الديناميكية عند طلبها لأول مرة وتتوقّف تلقائيًا عند التوقف عن استخدامها.

الخدمات التي يمكن تشغيلها ديناميكيًا

لا تتوفّر هذه الميزة إلا للخدمات الأصلية التي يمكن التحكّم في مراحل حياتها من خلال init وservicemanager. لا يُسمح باستخدام الخدمات ضمن حِزم التطبيقات، ويجب استخدام الخدمات المرتبطة بدلاً منها.

يعمل الإيقاف الديناميكي من خلال إيقاف العملية التي تعمل فيها الخدمة. إذا كانت هناك خدمات متعدّدة في العملية نفسها، يجب تسجيلها جميعًا كخدمات ديناميكية لتتوافق مع هذه الميزة. سيتم إيقاف هذه العملية بعد ذلك عندما لا يتم استخدام جميع الخدمات.

ضبط ملف init .rc للخدمة

لتشغيل خدمة بشكل ديناميكي، أضِف الخيارات التالية إلى ملف init .rc للخدمة بعد السطر service <name> <cmd>.

interface aidl serviceName
disabled
oneshot

وتعمل هذه الخيارات على تنفيذ ما يلي:

  • interface aidl serviceName: يسمح هذا الإذن servicemanager بالعثور على الخدمة. إذا كانت الخدمة تستخدم واجهات متعددة، يجب تحديد كل واجهة على سطر منفصل. يجب أن تكون هذه الأسماء مطابقة تمامًا لما يتوقّعه servicemanager، وقد تختلف عن اسم العملية.
  • disabled: يمنع بدء الخدمة تلقائيًا عند بدء التشغيل.
  • oneshot: يمنع إعادة تشغيل الخدمة تلقائيًا في كل مرة يتم إيقافها.

لمزيد من المعلومات، يُرجى الاطّلاع على ملف Readme الخاص بلغة Android Init في 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