لایه انتزاعی سختافزار حسگرها (HAL) رابط بین چارچوب حسگر اندروید و حسگرهای دستگاه، مانند شتابسنج یا ژیروسکوپ، است. HAL حسگرها توابعی را تعریف میکند که باید پیادهسازی شوند تا چارچوب بتواند حسگرها را کنترل کند.
حسگرهای HAL 2.0 در اندروید ۱۰ و بالاتر برای دستگاههای جدید و ارتقا یافته موجود است. حسگرهای HAL 2.0 مبتنی بر حسگرهای HAL 1.0 است اما چندین تفاوت کلیدی دارد که مانع از سازگاری آن با نسخههای قبلی میشود. حسگرهای HAL 2.0 از صفهای پیام سریع (FMQ) برای ارسال رویدادهای حسگر از HAL به چارچوب حسگر اندروید استفاده میکنند.
حسگرهای HAL 2.1 در اندروید ۱۱ و بالاتر برای دستگاههای جدید و ارتقا یافته موجود است. حسگرهای HAL 2.1 نسخهای از حسگرهای HAL 2.0 است که نوع حسگر HINGE_ANGLE را در معرض نمایش قرار میدهد و روشهای مختلف را برای پذیرش نوع HINGE_ANGLE بهروزرسانی میکند.
رابط HAL 2.1
منبع اصلی مستندات مربوط به Sensors HAL 2.1 در تعریف HAL در hardware/interfaces/sensors/2.1/ISensors.hal قرار دارد. در صورت وجود تضاد الزامات بین این صفحه و ISensors.hal ، از الزامات موجود در ISensors.hal استفاده کنید.
رابط HAL 2.0
منبع اصلی مستندات برای Sensors HAL 2.0 در تعریف HAL در hardware/interfaces/sensors/2.0/ISensors.hal قرار دارد. اگر بین الزامات این صفحه و ISensors.hal تضادی وجود دارد، از الزامات موجود در ISensors.hal استفاده کنید.
پیادهسازی حسگرهای HAL 2.0 و HAL 2.1
برای پیادهسازی Sensors HAL نسخههای ۲.۰ یا ۲.۱، یک شیء باید رابط ISensors را بسط داده و تمام توابع تعریفشده در 2.0/ISensors.hal یا 2.1/ISensors.hal را پیادهسازی کند.
مقداردهی اولیه HAL
حسگرهای HAL قبل از استفاده باید توسط چارچوب حسگر اندروید مقداردهی اولیه شوند. این چارچوب تابع initialize() را برای HAL 2.0 و تابع initialize_2_1() را برای HAL 2.1 فراخوانی میکند تا سه پارامتر به حسگرهای HAL ارائه دهد: دو توصیفگر FMQ و یک اشارهگر به یک شیء ISensorsCallback .
HAL از اولین توصیفگر برای ایجاد Event FMQ که برای نوشتن رویدادهای حسگر در چارچوب استفاده میشود، استفاده میکند. HAL از دومین توصیفگر برای ایجاد Wake Lock FMQ که برای همگامسازی هنگام آزاد شدن قفل بیداری HAL برای رویدادهای حسگر WAKE_UP استفاده میشود، استفاده میکند. HAL باید یک اشارهگر به شیء ISensorsCallback ذخیره کند تا هرگونه تابع فراخوانی لازم بتواند فراخوانی شود.
تابع initialize() یا initialize_2_1() باید اولین تابعی باشد که هنگام مقداردهی اولیه حسگرهای HAL فراخوانی میشود.
حسگرهای موجود را افشا کنید
برای دریافت لیستی از تمام سنسورهای استاتیک موجود در دستگاه، از تابع getSensorsList() در HAL 2.0 و تابع getSensorsList_2_1() در HAL 2.1 استفاده کنید. این تابع لیستی از سنسورها را برمیگرداند که هر کدام به طور منحصر به فرد با شناسه (handle) خود مشخص میشوند. شناسه یک سنسور مشخص نباید هنگام راهاندازی مجدد فرآیند میزبان سنسورهای HAL تغییر کند. شناسهها ممکن است در راهاندازی مجدد دستگاه و راهاندازی مجدد سرور سیستم تغییر کنند.
اگر چندین حسگر، نوع حسگر و ویژگی بیدارباش یکسانی داشته باشند، اولین حسگر موجود در لیست، حسگر پیشفرض نامیده میشود و به برنامههایی که از تابع getDefaultSensor(int sensorType, bool wakeUp) استفاده میکنند، بازگردانده میشود.
پایداری فهرست حسگرها
پس از راهاندازی مجدد Sensors HAL، اگر دادههای برگردانده شده توسط getSensorsList() یا getSensorsList_2_1() تغییر قابل توجهی را در مقایسه با لیست حسگرهای بازیابی شده قبل از راهاندازی مجدد نشان دهند، چارچوب، راهاندازی مجدد Android runtime را آغاز میکند. تغییرات قابل توجه در لیست حسگرها شامل مواردی است که یک حسگر با یک دسته مشخص وجود ندارد یا ویژگیهای آن تغییر کرده است، یا حسگرهای جدیدی معرفی میشوند. اگرچه راهاندازی مجدد Android runtime برای کاربر مختل کننده است، اما ضروری است زیرا چارچوب اندروید دیگر نمیتواند قرارداد API اندروید را برآورده کند که حسگرهای ایستا (غیرپویا) در طول عمر یک برنامه تغییر نمیکنند. این امر همچنین ممکن است مانع از برقراری مجدد درخواستهای حسگر فعال توسط برنامهها توسط چارچوب شود. بنابراین، به فروشندگان HAL توصیه میشود از تغییرات قابل اجتناب در لیست حسگرها جلوگیری کنند.
برای اطمینان از پایداری دستههای حسگر، HAL باید به طور قطعی یک حسگر فیزیکی مشخص در دستگاه را به دسته آن نگاشت کند. اگرچه هیچ پیادهسازی خاصی توسط رابط Sensors HAL الزامی نشده است، توسعهدهندگان گزینههای مختلفی برای برآورده کردن این الزام در اختیار دارند.
برای مثال، فهرست حسگرها را میتوان با استفاده از ترکیبی از ویژگیهای ثابت هر حسگر، مانند فروشنده، مدل و نوع حسگر، مرتب کرد. گزینه دیگر به این واقعیت متکی است که مجموعه حسگرهای ثابت دستگاه از نظر سختافزاری ثابت هستند، بنابراین HAL باید بداند که چه زمانی همه حسگرهای مورد انتظار، مقداردهی اولیه را قبل از بازگشت از getSensorsList() یا getSensorsList_2_1() تکمیل کردهاند. این فهرست از حسگرهای مورد انتظار را میتوان در فایل باینری HAL کامپایل کرد یا در یک فایل پیکربندی در سیستم فایل ذخیره کرد و ترتیب ظاهر شدن آنها را میتوان برای استخراج هندلهای پایدار استفاده کرد. اگرچه بهترین راه حل به جزئیات پیادهسازی خاص HAL شما بستگی دارد، اما شرط اصلی این است که هندلهای حسگر در طول راهاندازی مجدد HAL تغییر نکنند.
پیکربندی حسگرها
قبل از فعال شدن یک سنسور، باید با استفاده از تابع batch() یک دوره نمونهبرداری و حداکثر تأخیر گزارشدهی برای آن پیکربندی شود.
یک حسگر باید بتواند در هر زمانی با استفاده از batch() بدون از دست دادن دادههای حسگر، مجدداً پیکربندی شود.
دوره نمونهبرداری
دوره نمونهبرداری بسته به نوع حسگری که پیکربندی میشود، معنای متفاوتی دارد:
- پیوسته: رویدادهای حسگر با سرعت پیوسته تولید میشوند.
- در حال تغییر: رویدادها سریعتر از دوره نمونهبرداری تولید نمیشوند و اگر مقدار اندازهگیری شده تغییر نکند، ممکن است با سرعتی کندتر از دوره نمونهبرداری تولید شوند.
- یکباره: دوره نمونهبرداری نادیده گرفته میشود.
- ویژه: برای جزئیات بیشتر، به انواع حسگر مراجعه کنید.
برای کسب اطلاعات در مورد تعامل بین دوره نمونهبرداری و حالتهای گزارشدهی حسگر، به حالتهای گزارشدهی مراجعه کنید.
حداکثر تأخیر گزارشدهی
حداکثر تأخیر گزارش، حداکثر زمان (بر حسب نانوثانیه) را تعیین میکند که رویدادها میتوانند قبل از نوشتن در Event FMQ از طریق HAL در حالی که SoC بیدار است، در FIFO سختافزاری به تأخیر افتاده و ذخیره شوند.
مقدار صفر نشان میدهد که رویدادها باید به محض اندازهگیری گزارش شوند، یا به طور کلی از FIFO صرف نظر میشود، یا به محض اینکه یک رویداد از سنسور در FIFO وجود داشته باشد، FIFO خالی میشود.
برای مثال، یک شتابسنج که با فرکانس ۵۰ هرتز و حداکثر تأخیر گزارش صفر فعال میشود، در حالت آمادهباش SoC، ۵۰ بار در ثانیه وقفه ایجاد میکند.
وقتی حداکثر تأخیر گزارشدهی بیشتر از صفر باشد، نیازی نیست رویدادهای حسگر به محض شناسایی گزارش شوند. رویدادها میتوانند به طور موقت در سختافزار FIFO ذخیره شوند و به صورت دستهای گزارش شوند، مادامی که هیچ رویدادی بیش از حداکثر تأخیر گزارشدهی به تأخیر نیفتد. تمام رویدادها از دسته قبلی به بعد ضبط و به طور همزمان بازگردانده میشوند. این امر تعداد وقفههای ارسالی به SoC را کاهش میدهد و به SoC اجازه میدهد تا در حالی که حسگر در حال ثبت و دستهبندی دادهها است، به حالت مصرف انرژی پایینتری تغییر کند.
هر رویداد یک مهر زمانی مرتبط با خود دارد. تأخیر در زمان گزارش یک رویداد نباید بر مهر زمانی رویداد تأثیر بگذارد. مهر زمانی باید دقیق باشد و مطابق با زمانی باشد که رویداد به صورت فیزیکی اتفاق افتاده است، نه زمانی که گزارش شده است.
برای اطلاعات و الزامات بیشتر در مورد گزارش رویدادهای حسگر با حداکثر تأخیر گزارش غیر صفر، به بخش دستهبندی مراجعه کنید.
فعال کردن حسگرها
این چارچوب با استفاده از تابع activate() حسگرها را فعال و غیرفعال میکند. قبل از فعال کردن یک حسگر، چارچوب ابتدا باید حسگر را با استفاده از batch() پیکربندی کند.
پس از غیرفعال شدن یک حسگر، رویدادهای حسگر اضافی از آن حسگر نباید در Event FMQ نوشته شوند.
سنسورهای فلاش
اگر یک سنسور برای دسته بندی دادههای سنسور پیکربندی شده باشد، چارچوب میتواند با فراخوانی flush() یک پاکسازی فوری از رویدادهای سنسور دسته بندی شده را اعمال کند. این باعث میشود رویدادهای سنسور دسته بندی شده برای دسته سنسور مشخص شده بلافاصله در Event FMQ نوشته شوند. HAL سنسورها باید یک رویداد پاکسازی کامل را به انتهای رویدادهای سنسور که در نتیجه فراخوانی flush() نوشته شدهاند، اضافه کند.
عملیات flush به صورت غیرهمزمان اتفاق میافتد (یعنی، این تابع باید بلافاصله مقدار بازگشتی را برگرداند). اگر پیادهسازی از یک FIFO واحد برای چندین حسگر استفاده کند، آن FIFO خالی میشود و رویداد flush complete فقط برای حسگر مشخص شده اضافه میشود.
اگر سنسور مشخص شده FIFO نداشته باشد (امکان بافر کردن وجود نداشته باشد)، یا اگر FIFO در زمان فراخوانی خالی باشد، flush() همچنان باید موفق شود و یک رویداد flush complete برای آن سنسور ارسال کند. این موضوع در مورد همه سنسورها به غیر از سنسورهای one-shot صدق میکند.
اگر flush() برای یک سنسور تک مرحلهای فراخوانی شود، flush() باید BAD_VALUE برگرداند و رویداد flush complete را ایجاد نکند.
رویدادهای حسگر را در FMQ بنویسید
Event FMQ توسط Sensors HAL برای ارسال رویدادهای حسگر به چارچوب حسگر اندروید استفاده میشود.
FMQ رویداد یک FMQ هماهنگ است، به این معنی که هرگونه تلاش برای نوشتن رویدادهای بیشتر در FMQ نسبت به فضای موجود، منجر به نوشتن ناموفق میشود. در چنین حالتی، HAL باید تعیین کند که آیا مجموعه فعلی رویدادها را به صورت دو گروه کوچکتر از رویدادها بنویسد یا وقتی فضای کافی در دسترس باشد، همه رویدادها را با هم بنویسد.
وقتی HAL مربوط به سنسورها تعداد دلخواه از رویدادهای سنسور را در Event FMQ نوشت، HAL مربوط به سنسورها باید با نوشتن بیت EventQueueFlagBits::READ_AND_PROCESS در EventFlag::wake مربوط به Event FMQ، به چارچوب اطلاع دهد که رویدادها آماده هستند. EventFlag را میتوان از Event FMQ با استفاده از EventFlag::createEventFlag و تابع getEventFlagWord() مربوط به Event FMQ ایجاد کرد.
حسگرهای HAL 2.0/2.1 از هر دو 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 اجازه میدهد قفل بیدارباش خود را آزاد کند. برای همگامسازی زمانی که Sensors HAL قفل بیدارباش خود را آزاد میکند، از Wake Lock FMQ استفاده کنید.
حسگرهای HAL باید FMQ مربوط به قفل بیداری را بخوانند تا تعداد رویدادهای WAKE_UP که چارچوب مدیریت کرده است را تعیین کنند. HAL فقط باید قفل بیداری خود را برای رویدادهای WAKE_UP آزاد کند اگر تعداد کل رویدادهای WAKE_UP مدیریت نشده صفر باشد. پس از مدیریت رویدادهای حسگر، چارچوب تعداد رویدادهایی را که به عنوان رویدادهای WAKE_UP علامت گذاری شده اند، می شمارد و این عدد را در FMQ قفل بیداری می نویسد.
این چارچوب، هر زمان که دادهها را در Wake Lock FMQ مینویسد، اعلان نوشتن WakeLockQueueFlagBits::DATA_WRITTEN را روی Wake Lock FMQ تنظیم میکند.
حسگرهای دینامیکی
حسگرهای دینامیکی، حسگرهایی هستند که از نظر فیزیکی جزئی از دستگاه نیستند اما میتوانند به عنوان ورودی به دستگاه استفاده شوند، مانند یک دسته بازی با شتابسنج.
وقتی یک حسگر پویا متصل میشود، تابع onDynamicSensorConnected در ISensorsCallback باید از Sensors HAL فراخوانی شود. این کار، چارچوب حسگر پویای جدید را مطلع میکند و به حسگر اجازه میدهد تا از طریق چارچوب کنترل شود و رویدادهای حسگر توسط کلاینتها مصرف شوند.
به طور مشابه، وقتی یک حسگر پویا قطع میشود، تابع onDynamicSensorDisconnected در ISensorsCallback باید فراخوانی شود تا چارچوب بتواند هر حسگری را که دیگر در دسترس نیست، حذف کند.
کانال مستقیم
کانال مستقیم روشی برای عملکرد است که در آن رویدادهای حسگر به جای نوشتن در Event FMQ، با دور زدن چارچوب حسگرهای اندروید، در حافظه خاصی نوشته میشوند. کلاینتی که یک کانال مستقیم ثبت میکند، باید رویدادهای حسگر را مستقیماً از حافظهای که برای ایجاد کانال مستقیم استفاده شده است، بخواند و رویدادهای حسگر را از طریق چارچوب دریافت نخواهد کرد. تابع configDirectReport() برای عملکرد عادی مشابه تابع batch() است و کانال گزارش مستقیم را پیکربندی میکند.
توابع registerDirectChannel() و unregisterDirectChannel() یک کانال مستقیم جدید ایجاد یا از بین میبرند.
حالتهای عملیاتی
تابع setOperationMode() به چارچوب اجازه میدهد تا یک حسگر را پیکربندی کند تا چارچوب بتواند دادههای حسگر را به حسگر تزریق کند. این برای آزمایش، به خصوص برای الگوریتمهایی که در زیر چارچوب وجود دارند، مفید است.
تابع injectSensorData() در HAL 2.0 و تابع injectSensorsData_2_1() در HAL 2.0 معمولاً برای وارد کردن پارامترهای عملیاتی به حسگرهای HAL استفاده میشوند. این تابع همچنین میتواند برای تزریق رویدادهای حسگر به یک حسگر خاص استفاده شود.
اعتبارسنجی
برای اعتبارسنجی پیادهسازی حسگرهای HAL، آزمایشهای CTS و VTS حسگر را اجرا کنید.
آزمایشهای CTS
تستهای CTS حسگر هم در تستهای خودکار CTS و هم در برنامه تأییدکننده دستی CTS وجود دارند.
تستهای خودکار در مسیر cts/tests/sensor/src/android/hardware/cts قرار دارند. این تستها عملکرد استاندارد سنسورها، مانند فعالسازی سنسورها، دستهبندی و نرخ رویدادهای سنسور را بررسی میکنند.
آزمایشهای CTS Verifier در cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors قرار دارند. این آزمایشها نیاز به ورودی دستی از اپراتور آزمایش دارند و تضمین میکنند که حسگرها مقادیر دقیقی را گزارش میدهند.
قبولی در آزمونهای CTS برای اطمینان از اینکه دستگاه تحت آزمایش تمام الزامات CDD را برآورده میکند، بسیار مهم است.
آزمایشهای VTS
تستهای VTS برای سنسورهای HAL 2.0 در hardware/interfaces/sensors/2.0/vts قرار دارند. تستهای VTS برای سنسورهای HAL 2.1 در hardware/interfaces/sensors/2.1/vts قرار دارند. این تستها تضمین میکنند که سنسورهای HAL به درستی پیادهسازی شدهاند و تمام الزامات موجود در ISensors.hal و ISensorsCallback.hal به درستی برآورده شدهاند.
ارتقا به سنسورهای HAL 2.1 از ۲.۰
هنگام ارتقاء به Sensors HAL 2.1 از نسخه ۲.۰، پیادهسازی HAL شما باید شامل متدهای initialize_2_1() ، getSensorsList_2_1() و injectSensorsData_2_1() به همراه انواع HAL 2.1 باشد. این متدها باید همان الزامات ذکر شده برای HAL 2.0 در بالا را برآورده کنند.
از آنجا که HAL های نسخه فرعی باید از تمام توابع HAL های قبلی پشتیبانی کنند، HAL های نسخه ۲.۱ باید از مقداردهی اولیه به عنوان HAL های نسخه ۲.۰ پشتیبانی کنند. برای جلوگیری از پیچیدگی پشتیبانی از هر دو نسخه HAL، اکیداً توصیه میشود از Multi-HAL 2.1 استفاده کنید.
برای مثالی از نحوه پیادهسازی Sensors 2.1 HAL خودتان، به Sensors.h مراجعه کنید.
ارتقا به سنسورهای HAL 2.0 از ۱.۰
هنگام ارتقاء از نسخه ۱.۰ به Sensors HAL 2.0، اطمینان حاصل کنید که پیادهسازی HAL شما الزامات زیر را برآورده میکند.
مقداردهی اولیه HAL
برای ایجاد FMQها بین چارچوب و HAL، باید از تابع initialize() پشتیبانی شود.
حسگرهای موجود را افشا کنید
در Sensors HAL 2.0، تابع getSensorsList() باید در طول بوت یک دستگاه واحد، حتی در سراسر Sensors HAL که مجدداً راهاندازی میشوند، مقدار یکسانی را برگرداند. یک الزام جدید برای تابع getSensorsList() این است که باید در طول بوت یک دستگاه واحد، حتی در سراسر Sensors HAL که مجدداً راهاندازی میشوند، مقدار یکسانی را برگرداند. این امر به چارچوب اجازه میدهد تا در صورت راهاندازی مجدد سرور سیستم، اتصالات حسگر را دوباره برقرار کند. مقدار برگردانده شده توسط getSensorsList() میتواند پس از راهاندازی مجدد دستگاه تغییر کند.
رویدادهای حسگر را در FMQ بنویسید
به جای انتظار برای فراخوانی poll() ، در Sensors HAL 2.0، Sensors HAL باید هر زمان که رویدادهای حسگر در دسترس هستند، رویدادهای حسگر را به صورت پیشگیرانه در Event FMQ بنویسد. HAL همچنین مسئول نوشتن بیتهای صحیح در EventFlag است تا باعث خواندن FMQ در چارچوب شود.
رویدادهای بیداری (WAKE_UP)
در Sensors HAL 1.0، HAL میتوانست قفل بیدارباش خود را برای هر رویداد WAKE_UP در هر فراخوانی بعدی به poll() پس از ارسال WAKE_UP به poll() آزاد کند، زیرا این نشان میداد که چارچوب تمام رویدادهای حسگر را پردازش کرده و در صورت لزوم قفل بیدارباش دریافت کرده است. از آنجا که در Sensors HAL 2.0، HAL دیگر نمیداند چه زمانی چارچوب رویدادهای نوشته شده در FMQ را پردازش کرده است، Wake Lock FMQ به چارچوب اجازه میدهد تا پس از مدیریت رویدادهای WAKE_UP با HAL ارتباط برقرار کند.
در Sensors HAL 2.0، قفل بیداری که توسط Sensors HAL برای رویدادهای WAKE_UP ایمن شده است، باید با SensorsHAL_WAKEUP شروع شود.
حسگرهای دینامیکی
حسگرهای پویا با استفاده از تابع poll() در Sensors HAL 1.0 برگردانده شدند. Sensors HAL 2.0 مستلزم آن است که onDynamicSensorsConnected و onDynamicSensorsDisconnected در ISensorsCallback هر زمان که اتصالات حسگر پویا تغییر میکند، فراخوانی شوند. این فراخوانیهای برگشتی به عنوان بخشی از اشارهگر ISensorsCallback که از طریق تابع initialize() ارائه میشود، در دسترس هستند.
حالتهای عملیاتی
حالت DATA_INJECTION برای سنسورهای WAKE_UP باید در Sensors HAL 2.0 پشتیبانی شود.
پشتیبانی از چند HAL
حسگرهای HAL نسخههای ۲.۰ و ۲.۱ با استفاده از چارچوب حسگرهای Multi-HAL از چند-HAL پشتیبانی میکنند. برای جزئیات پیادهسازی، به بخش انتقال از حسگرهای HAL نسخه ۱.۰ مراجعه کنید.