«لایه انتزاعی سختافزار حسگرها» (HAL) رابط بین چارچوب حسگر Android و حسگرهای دستگاه، مثل شتابسنج یا ژیروسکوپ است. «لایه انتزاعی سختافزار حسگرها» عملکردهایی را تعریف میکند که باید پیادهسازی شوند تا چارچوب بتواند حسگرها را کنترل کند.
Sensors AIDL HAL در Android نسخه ۱۳ و بالاتر برای دستگاههای جدید و ارتقایافته دردسترس است. Sensors AIDL HAL که براساس Sensors HAL 2.1 است، از میانای AIDL HAL استفاده میکند و انواع حسگرهای ردیاب سر و IMU با محور محدود را نشان میدهد.
میانای HAL در AIDL
منبع اصلی اسناد برای Sensors AIDL HAL در تعریف HAL در hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl قرار دارد.
پیادهسازی Sensors AIDL HAL
برای پیادهسازی Sensors AIDL HAL، شیء باید از رابط ISensors
گسترش یابد و همه عملکردهای تعریفشده در
hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl را پیادهسازی کند.
مقداردهی اولیه HAL
«لایه انتزاع سختافزاری حسگرها» باید قبلاز استفاده توسط چارچوب حسگر Android مقداردهی اولیه شود. چارچوب تابع initialize() را فرا میخواند تا سه پارامتر به «لایه انتزاع سختافزاری حسگرها» ارائه دهد: دو توصیفگر FMQ و یک اشارهگر به شیء ISensorsCallback.
HAL از توصیفگر اول برای ایجاد FMQ رویداد استفاده میکند که برای نوشتن رویدادهای حسگر در چارچوب استفاده میشود. «لایه انتزاعی سختافزار» از توصیفگر دوم برای ایجاد Wake
Lock FMQ استفاده میکند که برای همگامسازی زمانی که «لایه انتزاعی سختافزار» قفل بیداری خود را برای رویدادهای حسگر WAKE_UP
آزاد میکند استفاده میشود. HAL باید اشارهگری به شیء ISensorsCallback ذخیره کند تا
هر تابع بازخوانی لازم بتواند فراخوانده شود.
تابع initialize() باید اولین تابعی باشد که هنگام مقداردهی اولیه
«لایه انتزاع سختافزاری حسگرها» فراخوانی میشود.
نمایش حسگرهای دردسترس
برای دریافت فهرستی از همه حسگرهای ایستا دردسترس در دستگاه، از تابع
getSensorsList() استفاده کنید. این تابع فهرستی از حسگرها را برمیگرداند که هرکدام
با دستگیره خود بهطور منحصربهفرد شناسایی میشوند. وقتی فرایند میزبانی Sensors HAL بازراهاندازی میشود،
دستگیره حسگر نباید تغییر کند. نامهای کاربری ممکن است در
بازراهاندازی دستگاه و در بازراهاندازی سرور سیستم تغییر کنند.
اگر چند حسگر نوع حسگر و ویژگی بیدار شدن یکسانی داشته باشند،
اولین حسگر در فهرست حسگر پیشفرض نامیده میشود و به
برنامههایی که از تابع getDefaultSensor(int sensorType, bool wakeUp) استفاده میکنند
برگردانده میشود.
پایداری فهرست حسگرها
پساز بازراهاندازی «لایه انتزاع سختافزاری حسگرها»، اگر دادههای برگشتی توسط getSensorsList()
در مقایسه با فهرست حسگر بازیابیشده قبلاز
بازراهاندازی، تغییر قابلتوجهی را نشان دهد، چارچوب
بازراهاندازی زمان اجرای Android را راهاندازی میکند. تغییرات قابلتوجه در فهرست حسگرها شامل مواردی است که حسگری با دستگیره مشخص وجود ندارد یا ویژگیهای آن تغییر کرده است، یا حسگرهای جدیدی معرفی شدهاند. اگرچه راهاندازی مجدد زمان اجرای Android برای کاربر مزاحمت ایجاد میکند، اما این کار لازم است زیرا چارچوب Android دیگر نمیتواند قرارداد Android API را که طبق آن حسگرهای ایستا (غیرپویا) درطول عمر برنامه تغییر نمیکنند برآورده کند. این کار همچنین ممکن است از برقراری مجدد درخواستهای حسگر فعال که توسط برنامهها انجام شده است جلوگیری کند. بنابراین، به فروشندگان HAL توصیه میشود
از تغییرات غیرضروری در فهرست حسگرها جلوگیری کنند.
برای اطمینان از پایداری دستههای حسگر، HAL باید بهطور قطعی یک حسگر فیزیکی معین در دستگاه را به دسته آن نگاشت کند. اگرچه هیچ پیادهسازی خاصی توسط رابط HAL «حسگرها» الزامی نیست، توسعهدهندگان گزینههای متعددی برای برآورده کردن این الزام دارند.
برای مثال، فهرست حسگر را میتوان بااستفاده از ترکیبی از مشخصههای ثابت هر حسگر، مثل فروشنده، مدل، و نوع حسگر، مرتب کرد. گزینه دیگر به این واقعیت متکی است که مجموعه حسگرهای ثابت دستگاه در سختافزار ثابت است، بنابراین HAL باید بداند چه زمانی همه حسگرهای موردانتظار مقداردهی اولیه را تکمیل کردهاند تا بتواند از getSensorsList() برگردد. این فهرست از
حسگرهای موردانتظار را میتوان در دودویی HAL کامپایل کرد یا در
فایل پیکربندی در سیستم فایل ذخیره کرد، و از ترتیب ظاهر شدن میتوان برای
استخراج دستگیرههای پایدار استفاده کرد. اگرچه بهترین راهحل به جزئیات پیادهسازی خاص HAL شما بستگی دارد، اما نیاز کلیدی این است که دستههای حسگر در راهاندازی مجدد HAL تغییر نکنند.
پیکربندی حسگرها
پیشاز فعال شدن حسگر، حسگر باید با دوره نمونهبرداری و حداکثر تأخیر گزارشدهی بااستفاده از تابع batch() پیکربندی شود.
حسگر باید بتواند در هرزمانی بااستفاده از batch() بدون ازدست دادن دادههای حسگر دوباره پیکربندی شود.
دوره نمونهگیری
دوره نمونهبرداری براساس نوع حسگری که پیکربندی میشود معنی متفاوتی دارد:
- پیوسته: رویدادهای حسگر با نرخ پیوسته تولید میشوند.
- تغییر: رویدادها سریعتر از دوره نمونهبرداری تولید نمیشوند و اگر مقدار اندازهگیریشده تغییر نکند، ممکن است با نرخی کندتر از دوره نمونهبرداری تولید شوند.
- تکضرب: دوره نمونهگیری نادیده گرفته میشود.
- ویژه: برای جزئیات بیشتر، انواع حسگر را ببینید.
برای آشنایی با تعامل بین دوره نمونهگیری و حالتهای گزارشدهی حسگر، حالتهای گزارشدهی را ببینید.
حداکثر تأخیر گزارشدهی
حداکثر تأخیر گزارشدهی حداکثر زمان برحسب نانوثانیه را تعیین میکند که رویدادها میتوانند در آن تأخیر داشته باشند و در سختافزار FIFO ذخیره شوند، سپس ازطریق HAL درحالیکه SoC بیدار است در Event FMQ نوشته شوند.
مقدار صفر نشان میدهد که رویدادها باید بهمحض اندازهگیری گزارش شوند، یا بهطور کامل از FIFO صرفنظر شود، یا بهمحض اینکه یک رویداد از حسگر در FIFO وجود داشته باشد، FIFO خالی شود.
برای مثال، شتابسنجی که در ۵۰ هرتز با حداکثر تأخیر گزارشدهی صفر فعال شده است، وقتی SoC بیدار است، ۵۰ بار در ثانیه وقفهها را راهاندازی میکند.
وقتی بیشینه تأخیر گزارشدهی بزرگتر از صفر باشد، رویدادهای حسگر لازم نیست بهمحض شناسایی گزارش شوند. رویدادها میتوانند بهطور موقت در سختافزار FIFO ذخیره شوند و بهصورت دستهای گزارش شوند، بهشرطی که هیچ رویدادی بیشاز حداکثر تأخیر گزارشدهی تأخیر نداشته باشد. همه رویدادهای پساز دسته قبلی بهطور همزمان ضبط و برگردانده میشوند. این کار تعداد وقفههای ارسالشده به SoC را کاهش میدهد و به SoC اجازه میدهد درحالیکه حسگر درحال ضبط و دستهبندی دادهها است، به حالت کممصرف برود.
هر رویداد دارای مُهر زمان منسوب به خود است. تأخیر در زمان گزارش رویداد نباید بر مُهر زمان رویداد تأثیر بگذارد. مهر زمان باید دقیق باشد و با زمانی که رویداد بهصورت فیزیکی رخ داده است مطابقت داشته باشد، نه زمانی که گزارش شده است.
برای اطلاعات بیشتر و الزامات گزارش رویدادهای حسگر با بیشینه تأخیر گزارش غیرصفر، به دستهای کردن مراجعه کنید.
فعال کردن حسگرها
این چارچوب بااستفاده از تابع activate() حسگرها را فعال و غیرفعال میکند.
پیشاز فعال کردن حسگر، چارچوب باید ابتدا حسگر را بااستفاده از batch() پیکربندی کند.
پساز غیرفعال شدن حسگر، رویدادهای حسگر اضافی از آن حسگر نباید در «صف پیام رویداد» نوشته شود.
حسگرهای فلاش
اگر حسگری برای دستهای کردن دادههای حسگر پیکربندی شده باشد، چارچوب میتواند با فراخوانی flush()،
حسگر رویدادهای دستهای را مجبور به تخلیه فوری کند. این کار باعث میشود رویدادهای حسگر دستهای برای دستگیره حسگر مشخصشده بلافاصله در FMQ رویداد نوشته شود. «لایه انتزاعی سختافزار حسگرها» باید رویداد تکمیل تخلیه را به انتهای رویدادهای حسگر که درنتیجه فراخوانی flush() نوشته شدهاند اضافه کند.
شستشو بهصورت غیرهمگام انجام میشود (یعنی این تابع باید بلافاصله برگردد). اگر پیادهسازی از یک FIFO برای چند حسگر استفاده کند، آن FIFO پاکسازی میشود و رویداد تکمیل پاکسازی فقط برای حسگر مشخصشده اضافه میشود.
اگر حسگر مشخصشده FIFO نداشته باشد (بافر کردن ممکن نباشد)، یا اگر FIFO در زمان تماس خالی باشد، flush() باید همچنان موفق شود و رویداد تکمیل پاکسازی را برای آن حسگر ارسال کند. این مورد برای همه حسگرها بهجز حسگرهای تکشات اعمال میشود.
اگر flush() برای حسگر یکباره فراخوانده شود، flush() باید
BAD_VALUE را برگرداند و رویداد تکمیل تخلیه تولید نکند.
نوشتن رویدادهای حسگر در FMQ
«صف پیام سریع رویداد» توسط «لایه انتزاعی سختافزار حسگرها» برای ارسال رویدادهای حسگر به چارچوب حسگر Android استفاده میشود.
«صف پیام سریع رویداد» یک «صف پیام سریع» همزمانسازیشده است، به این معنی که هرگونه تلاش برای نوشتن رویدادهای بیشتر در «صف پیام سریع» نسبتبه فضای دردسترس منجر به نوشتن ناموفق میشود. در چنین شرایطی، HAL باید تعیین کند که آیا مجموعه فعلی رویدادها را بهصورت دو گروه کوچکتر از رویدادها بنویسد یا همه رویدادها را با هم بنویسد، زمانی که فضای کافی دردسترس باشد.
وقتی «لایه انتزاعی سختافزار حسگرها» تعداد موردنظر رویدادهای حسگر را در
«صف پیام سریع رویداد» نوشت، «لایه انتزاعی سختافزار حسگرها» باید با نوشتن
بیت EventQueueFlagBits::READ_AND_PROCESS در تابع
EventFlag::wake «صف پیام سریع رویداد»، به چارچوب اطلاع دهد که رویدادها آمادهاند. EventFlag را میتوان از Event FMQ
بااستفاده از EventFlag::createEventFlag و تابع getEventFlagWord()
Event FMQ ایجاد کرد.
Sensors AIDL HAL از هر دو write و writeBlocking در Event FMQ پشتیبانی میکند.
پیادهسازی پیشفرض مرجعی برای استفاده از write ارائه میدهد. اگر از تابع
writeBlocking استفاده شود، پرچم readNotification باید روی
EventQueueFlagBits::EVENTS_READ تنظیم شود که توسط چارچوب هنگام خواندن
رویدادها از Event FMQ تنظیم میشود. پرچم اعلان نوشتن باید روی
EventQueueFlagBits::READ_AND_PROCESS تنظیم شود که به چارچوب اطلاع میدهد رویدادها
در Event FMQ نوشته شدهاند.
رویدادهای WAKE_UP
WAKE_UP رویداد، رویداد حسگر است که باعث میشود پردازنده برنامه (AP) بیدار شود و رویداد را فوراً مدیریت کند. هرگاه رویداد WAKE_UP در
Event FMQ نوشته شود، Sensors HAL باید قفل بیدارباش را ایمن کند تا مطمئن شود که
سیستم تا زمانی که چارچوب بتواند رویداد را مدیریت کند بیدار میماند. پساز دریافت رویداد
WAKE_UP، چارچوب قفل بیدارباش خود را ایمن میکند و به
«لایه انتزاعی سختافزار حسگرها» اجازه میدهد قفل بیدارباش خود را آزاد کند. برای همگامسازی کردن زمانی که Sensors HAL
قفل بیداری را آزاد میکند، از Wake Lock FMQ استفاده کنید.
Sensors HAL باید Wake Lock FMQ را بخواند تا تعداد رویدادهای WAKE_UP را که چارچوب مدیریت کرده است تعیین کند. «لایه انتزاع سختافزار» فقط باید قفل بیداری خود را برای WAKE_UP رویدادها آزاد کند اگر تعداد کل رویدادهای WAKE_UP رسیدگینشده صفر باشد.
پساز رسیدگی به رویدادهای حسگر، چارچوب تعداد رویدادهایی را که بهعنوان رویدادهای WAKE_UP علامتگذاری شدهاند میشمارد و این تعداد را در Wake Lock FMQ بازنویسی میکند.
چارچوب هرگاه دادهای را در Wake Lock FMQ مینویسد، اعلان نوشتن WakeLockQueueFlagBits::DATA_WRITTEN را در Wake Lock FMQ تنظیم میکند.
حسگرهای پویا
حسگرهای پویا حسگرهایی هستند که ازنظر فیزیکی بخشی از دستگاه نیستند اما میتوانند بهعنوان ورودی دستگاه استفاده شوند، مثل دسته بازی با شتابسنج.
وقتی حسگر پویایی متصل میشود، تابع onDynamicSensorConnected در
ISensorsCallback باید از Sensors HAL فراخوانده شود. این کار چارچوب را از حسگر پویای جدید مطلع میکند و به حسگر اجازه میدهد ازطریق چارچوب کنترل شود و رویدادهای حسگر توسط کارخواهها مصرف شود.
بههمین ترتیب، وقتی حسگر پویایی قطع میشود، باید تابع
onDynamicSensorDisconnected در ISensorsCallback فراخوانی شود تا چارچوب بتواند هر حسگری را که دیگر دردسترس نیست بردارد.
کانال مستقیم
کانال مستقیم روشی برای عملکرد است که در آن رویدادهای حسگر بهجای «صف پیام رویداد» در حافظه خاصی نوشته میشود و از «چارچوب حسگرهای Android» عبور میکند. کارخواهی که کانال مستقیمی را ثبت میکند باید رویدادهای حسگر را
مستقیماً از حافظهای که برای ایجاد کانال مستقیم استفاده شده است بخواند و
رویدادهای حسگر را ازطریق چارچوب دریافت نخواهد کرد. عملکرد configDirectReport()
مشابه batch() برای عملکرد عادی است و کانال گزارش مستقیم را پیکربندی میکند.
عملکردهای registerDirectChannel() و unregisterDirectChannel() کانال مستقیم جدیدی ایجاد
یا حذف میکنند.
حالتهای عملکرد
تابع setOperationMode() به چارچوب اجازه میدهد حسگر را پیکربندی کند
تا چارچوب بتواند دادههای حسگر را به حسگر تزریق کند. این ویژگی برای آزمایش کردن، بهویژه برای الگوریتمهایی که در زیر چارچوب وجود دارند، مفید است.
از تابع injectSensorData() معمولاً برای انتقال پارامترهای عملیاتی به
«لایه انتزاع سختافزار حسگرها» استفاده میشود. از این تابع همچنین میتوان برای تزریق رویدادهای حسگر به حسگر خاصی استفاده کرد.
اعتبارسنجی
برای اعتبارسنجی پیادهسازی «لایه انتزاعی سختافزار حسگرها»، آزمایشهای حسگر CTS و VTS را اجرا کنید.
آزمایشهای CTS
آزمایشهای حسگر CTS هم در آزمایشهای خودکارسازیشده CTS و هم در برنامه دستی CTS Verifier وجود دارد.
آزمایشهای خودکار در cts/tests/sensor/src/android/hardware/cts قرار دارند. این آزمایشها عملکرد استاندارد حسگرها را درستیسنجی میکنند، مثلاً فعال کردن حسگرها، دستهبندی، و نرخ رویداد حسگر.
آزمایشهای «درستیسنج CTS» در cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors قرار دارند. این آزمایشها نیاز به ورودی دستی ازسوی اپراتور آزمایش دارد و تضمین میکند که حسگرها مقادیر دقیق را گزارش کنند.
گذراندن آزمایشهای CTS برای اطمینان از اینکه دستگاه تحت آزمایش همه الزامات CDD را برآورده میکند بسیار مهم است.
آزمایشهای VTS
آزمایشهای VTS برای Sensors AIDL HAL در
hardware/interfaces/sensors/aidl/vts/ قرار دارند.
این آزمایشها تضمین میکنند که Sensors HAL بهدرستی پیادهسازی شده است و همه
الزامات ISensors.aidl و ISensorsCallback.aidl بهدرستی برآورده شدهاند.
مقداردهی اولیه HAL
برای ایجاد FMQ بین چارچوب و HAL، باید از تابع initialize() پشتیبانی شود.
نمایش حسگرهای دردسترس
در Sensors AIDL HAL، تابع getSensorsList() باید مقدار یکسانی را
درطول یک بوت دستگاه برگرداند، حتی درصورت بازراهاندازی Sensors HAL. یکی از الزامات جدید تابع getSensorsList() این است که باید درطول
یک راهاندازی دستگاه، حتی درصورت بازراهاندازی «لایه انتزاع سختافزاری حسگرها»، مقدار یکسانی را برگرداند. این کار به چارچوب اجازه میدهد درصورت بازراهاندازی سرور سیستم، برای برقراری مجدد اتصالهای حسگر تلاش کند. مقدار برگشتی از getSensorsList() میتواند پساز بازراهاندازی دستگاه تغییر کند.
نوشتن رویدادهای حسگر در FMQ
بهجای اینکه منتظر بمانید poll() فراخوانی شود، در Sensors AIDL HAL، هرگاه رویدادهای حسگر دردسترس باشد، Sensors HAL باید بهصورت پیشکنشی رویدادهای حسگر را در Event FMQ بنویسد. «لایه انتزاع سختافزار» همچنین مسئول نوشتن بیتهای صحیح در
EventFlag است تا باعث خواندن FMQ در چارچوب شود.
رویدادهای WAKE_UP
In Sensors HAL 1.0, the HAL was able to release its wake lock for any WAKE_UP
event on any subsequent call to poll() after a WAKE_UP was posted to
poll() because this indicated that the framework had processed all sensor
events and had obtained a wake lock, if necessary. ازآنجاییکه در Sensors AIDL
HAL، وقتی چارچوب رویدادهای
نوشتهشده در FMQ را پردازش میکند، دیگر به HAL اطلاع داده نمیشود، Wake Lock FMQ به چارچوب امکان میدهد وقتی WAKE_UP رویداد را مدیریت کرد به
HAL اطلاع دهد.
در Sensors AIDL HAL، قفل بیداری که Sensors HAL برای WAKE_UP
رویدادها ایمن کرده است باید با SensorsHAL_WAKEUP شروع شود.
حسگرهای پویا
حسگرهای پویا بااستفاده از تابع poll() در Sensors HAL 1.0 برگردانده شدند.
Sensors AIDL HAL لازم دارد که onDynamicSensorsConnected و
onDynamicSensorsDisconnected در ISensorsCallback هر زمان که اتصالات حسگر پویا تغییر میکند فراخوانی شوند. این توابع برگشتی بهعنوان بخشی از
اشارهگر ISensorsCallback که ازطریق تابع initialize() ارائه میشود دردسترس هستند.
حالتهای عملکرد
حالت DATA_INJECTION برای حسگرهای WAKE_UP باید پشتیبانی شود.
پشتیبانی از Multi-HAL
Sensors AIDL HAL از چند HAL بااستفاده از چارچوب Sensors Multi-HAL پشتیبانی میکند. برای جزئیات پیادهسازی، به انتقال از Sensors HAL 2.1 مراجعه کنید.