واجهات برمجة التطبيقات لأجهزة الاستشعار المتاحة ديناميكيًا

يتيح نظام التشغيل Android 9 إيقاف أنظمة Android المكوّنة الفرعية بشكل ديناميكي عندما لا تكون قيد الاستخدام أو غير مطلوبة. على سبيل المثال، عندما لا يستخدم أحد المستخدمين شبكة Wi-Fi، يجب ألا تستهلك الأنظمة الفرعية لشبكة Wi-Fi الذاكرة أو الطاقة أو موارد النظام الأخرى. في الإصدارات السابقة من Android، كانت واجهات HAL أو برامج التشغيل تظل مفتوحة على أجهزة Android طوال مدة تشغيل هاتف Android.

يتضمن تنفيذ الإيقاف الديناميكي ربط تدفقات البيانات وتنفيذ العمليات الديناميكية كما هو موضّح بالتفصيل في الأقسام التالية.

تغييرات على تعريفات HAL

يتطلّب الإيقاف الديناميكي معلومات عن العمليات التي توفّر واجهات HAL (قد تكون هذه المعلومات مفيدة أيضًا لاحقًا في سياقات أخرى)، وكذلك عدم بدء العمليات عند التشغيل وعدم إعادة تشغيلها (إلى أن تتم الإعادة مرة أخرى) عند الخروج.

# some init.rc script associated with the HAL
service vendor.some-service-name /vendor/bin/hw/some-binary-service
    # init language extension, provides information of what service is served
    # if multiple interfaces are served, they can be specified one on each line
    interface android.hardware.light@2.0::ILight default
    # restarted if hwservicemanager dies
    # would also cause the hal to start early during boot if disabled wasn't set
    class hal
    # will not be restarted if it exits until it is requested to be restarted
    oneshot
    # will only be started when requested
    disabled
    # ... other properties

التغييرات على init وhwservicemanager

يتطلّب الإيقاف الديناميكي أيضًا أن يطلب hwservicemanager من init بدء الخدمات المطلوبة. في Android 9، يحتوي init على ثلاث رسائل تحكّم إضافية (مثل ctl.start): ctl.interface_start وctl.interface_stop وctl.interface_restart. يمكن استخدام هذه الرسائل للإشارة إلى init لعرض واجهات أجهزة معيّنة وإخفائها. عند طلب خدمة غير مسجَّلة، يطلب hwservicemanager بدء الخدمة. ومع ذلك، لا تتطلّب واجهات HAL الديناميكية استخدام أيٍّ من هذه العناصر.

تحديد وقت خروج HAL

في Android 9، يجب تحديد مخرج HAL يدويًا. بالنسبة إلى Android 10 والإصدارات الأحدث، يمكن أيضًا تحديده باستخدام مراحل الحياة التلقائية.

يتطلب الإيقاف الديناميكي سياسات متعدّدة لتحديد وقت بدء HAL ووقت إيقاف HAL. إذا قرّر HAL الخروج لأي سبب، ستتم إعادة تشغيله تلقائيًا عند الحاجة إليه مرة أخرى باستخدام المعلومات المقدَّمة في تعريف HAL والبنية الأساسية المقدَّمة من خلال التغييرات على init وhwservicemanager. ويمكن أن يشمل ذلك استراتيجيتَين مختلفتَين، وهما:

  • يمكن أن يختار HAL طلب الخروج من نفسه إذا طلب أحد المستخدمين واجهة برمجة تطبيقات مشابهة أو قريبة منه. يجب تحديد هذا السلوك في واجهة HAL المقابلة.
  • يمكن إيقاف وحدات HAL عند اكتمال مهمتها (موثَّقة في ملف HAL ).

مراحل النشاط التلقائية

يضيف نظام التشغيل Android 10 المزيد من التوافق مع kernel و hwservicemanager، ما يسمح لواجهات HAL بالإيقاف التلقائي عندما لا يكون لديها عملاء. لاستخدام هذه الميزة، عليك تنفيذ جميع الخطوات الواردة في التغييرات على تعريفات HAL بالإضافة إلى:

  • سجِّل الخدمة في C++ باستخدام LazyServiceRegistrar بدلاً من الدالة العضو registerAsService، على سبيل المثال:
    // only one instance of LazyServiceRegistrar per process
    LazyServiceRegistrar registrar;
    registrar.registerAsService(myHidlService /* , "default" */);
  • تأكَّد من أنّ برنامج HAL يحفظ إشارة إلى HAL من المستوى الأعلى (واجهة العميل المسجَّلة باستخدام hwservicemanager) فقط عند استخدامها. لتجنُّب حدوث تأخيرات في حال تم إسقاط هذا المرجع في سلسلة مهام hwbinder التي تستمر في التنفيذ، يجب أن يستدعي العميل أيضًا IPCThreadState::self()->flushCommands() بعد إسقاط المرجع لضمان إرسال إشعار إلى برنامج تشغيل Binder بتغييرات عدد المرجع المرتبط.