שכבת ההפשטה של חומרת החיישנים (HAL) היא הממשק בין מסגרת החיישנים של Android לבין חיישני המכשיר, כמו מד תאוצה או ג'ירוסקופ. תקן HAL לחיישנים מגדיר את הפונקציות שצריך להטמיע כדי לאפשר ל-framework לשלוט בחיישנים.
ה-HAL של Sensors AIDL זמין ב-Android מגרסה 13 ואילך במכשירים חדשים ובמכשירים משודרגים. Sensors AIDL HAL, שמבוסס על Sensors HAL 2.1, משתמש בממשק AIDL HAL ומציג את סוגי חיישני ה-IMU למעקב אחר תנועות הראש וסוגי חיישני ה-IMU עם צירים מוגבלים.
ממשק AIDL HAL
מקור המסמכים הראשי של HAL ל-Sensors AIDL נמצא בהגדרת ה-HAL בכתובת hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
הטמעת HAL של Sensors AIDL
כדי להטמיע את HAL של Sensors AIDL, אובייקט צריך להרחיב את הממשק ISensors
ולהטמיע את כל הפונקציות שמוגדרות ב-hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
אתחול ה-HAL
לפני השימוש בחיישן HAL, יש לאתחל על ידי מסגרת החיישנים של Android. המסגרת קוראת לפונקציה initialize()
כדי לספק שלושה פרמטרים ל-HAL של החיישנים: שני מתארי FMQ ו-pointer אחד לאובייקט ISensorsCallback
.
ה-HAL משתמש בתיאור הראשון כדי ליצור את ה-Event FMQ שמשמש לכתיבת אירועי חיישנים למסגרת. ה-HAL משתמש במתאר השני כדי ליצור את ה-FMQ של Wake Lock, שמשמשים לסנכרון כשה-HAL משחרר את נעילת ההתעוררות שלו לאירועי חיישן WAKE_UP
. ה-HAL חייב לשמור מצביע לאובייקט ISensorsCallback
כדי שאפשר יהיה להפעיל את כל פונקציות ההתקשרות החוזרת הנדרשות.
הפונקציה initialize()
חייבת להיות הפונקציה הראשונה שנקראת באתחול HAL של החיישנים.
חשיפת החיישנים הזמינים
כדי לקבל רשימה של כל החיישנים הסטטיים הזמינים במכשיר, אפשר להשתמש בפונקציה getSensorsList()
. הפונקציה מחזירה רשימה של חיישנים, שכל אחד מהם מזוהה באופן ייחודי על ידי הכינוי שלו. ה-handle של חיישן נתון לא יכול להשתנות כשהתהליך שמארח את Sensors HAL מתחיל מחדש. הכינוי עשוי להשתנות אחרי הפעלה מחדש של המכשיר או אחרי הפעלה מחדש של שרת המערכת.
אם כמה חיישנים חולקים את אותו סוג חיישן ואת אותה מאפיין התעוררות, החיישן הראשון ברשימה נקרא חיישן ברירת המחדל והוא מוחזר לאפליקציות שמשתמשות בפונקציה getDefaultSensor(int sensorType, bool wakeUp)
.
יציבות רשימת החיישנים
אחרי הפעלה מחדש של ממשק החיישן עם HAL, אם הנתונים שהוחזרו על ידי getSensorsList()
מצביע על שינוי משמעותי בהשוואה לרשימת החיישנים שאוחזרו לפני ההפעלה מחדש, ה-framework יגרום להפעלה מחדש של סביבת זמן הריצה של Android. שינויים משמעותיים ברשימת החיישנים כוללים מקרים שבהם חיישן עם כינוי נתון חסר או שהמאפיינים שלו השתנו, או מקרים שבהם נוספו חיישנים חדשים. הפעלה מחדש של סביבת זמן הריצה של Android מפריעה למשתמש, אבל היא נדרשת כי מסגרת Android כבר לא יכולה לעמוד בתנאי החוזה של Android API, שלפיו חיישני סטטיים (לא דינמיים) לא משתנים במהלך מחזור החיים של אפליקציה. כתוצאה מכך, יכול להיות שהמסגרת לא תוכל ליצור מחדש בקשות חיישנים פעילות שנשלחות על ידי אפליקציות. לכן, מומלץ לספקי HAL למנוע שינויים שניתן להימנע משינויים ברשימת החיישנים.
כדי להבטיח שמזהי החיישנים יהיו יציבים, ה-HAL צריך למפות באופן דטרמיניסטי חיישן פיזי נתון במכשיר למזהה שלו. ממשק ה-HAL של חיישנים לא מחייב הטמעה ספציפית, אבל למפתחים יש כמה אפשרויות שעומדות בדרישות האלה.
לדוגמה, אפשר למיין את רשימת החיישנים באמצעות שילוב של המאפיינים הקבועים של כל חיישן, כמו ספק, דגם וסוג חיישן. אפשרות אחרת מבוססת על העובדה שקבוצת החיישנים הסטטיים של המכשיר קבועה בחומרה, ולכן ה-HAL צריך לדעת מתי כל החיישנים הצפויים השלימו את האינטוליזציה לפני שהוא חוזר מ-getSensorsList()
. אפשר לקמפל את רשימת החיישנים הצפויים לקובץ ה-HAL הבינארי או לאחסן אותה בקובץ תצורה במערכת הקבצים, וניתן להשתמש בסדר ההופעה כדי להפיק כינויים יציבים. הפתרון הטוב ביותר תלוי בפרטי ההטמעה הספציפיים של ה-HAL, אבל הדרישה העיקרית היא שהמזהים של החיישנים לא ישתנו במהלך הפעלות מחדש של ה-HAL.
הגדרת חיישנים
לפני שמפעילים חיישן, צריך להגדיר לו תקופת דגימה וזמן אחזור מקסימלי לדיווח באמצעות הפונקציה batch()
.
חיישן צריך להיות ניתן להגדרה מחדש בכל שלב באמצעות batch()
, בלי אובדן של נתוני החיישן.
תקופת הדגימה
לתקופה לדגימה יש משמעות שונה בהתאם לסוג החיישן שמוגדר:
- רציף: אירועי חיישנים נוצרים בקצב רציף.
- בזמן שינוי: האירועים נוצרים לא מהר יותר ממחזור הדגימה, ויכול להיות שהם נוצרים בקצב איטי יותר ממחזור הדגימה אם הערך שנמדד לא משתנה.
- חד-פעמית: תקופת הדגימה מתעלמת.
- מיוחדים: למידע נוסף, ראו סוגי חיישנים.
למידע על האינטראקציה בין תקופת הדגימה למצבי הדיווח של חיישן, ראו מצבי דיווח.
זמן אחזור מקסימלי לדיווח
זמן האחזור המקסימלי לדיווח קובע את הזמן המקסימלי בננו-שניות שבו אירועים יכולים להתעכב ולאחסן ב-FIFO של החומרה לפני שהם נכתבים ל-Event FMQ דרך HAL בזמן שה-SoC לא פעיל.
ערך של אפס פירושו שצריך לדווח על האירועים מיד לאחר המדידה שלהם, לדלג על ה-FIFO לגמרי או לרוקן את ה-FIFO ברגע שאירוע אחד מהחיישן נמצא ב-FIFO.
לדוגמה, תאוצה שמופעל ב-50 Hz עם זמן אחזור מקסימלי לדיווח של אפס מפעילה הפסקות 50 פעמים בשנייה כש-SoC פעיל.
כשזמן האחזור המקסימלי לדיווח גדול מאפס, אין צורך לדווח על אירועי חיישנים ברגע שהם מזוהים. אפשר לאחסן אירועים באופן זמני ב-FIFO של החומרה ולדווח עליהם בקבוצות, כל עוד אף אירוע לא מתעכב יותר מזמן האחזור המקסימלי לדיווח. כל האירועים מאז המקבץ הקודם מתועדים ומוחזרים בבת אחת. כך מופחת מספר ההפרעות שנשלחות ל-SoC, ומאפשר ל-SoC לעבור למצב צריכת אנרגיה נמוכה יותר בזמן שהחיישן מתעד את הנתונים ומקבץ אותם.
לכל אירוע יש חותמת זמן משויכת. עיכוב בדיווח על אירוע לא יכול להשפיע על חותמת הזמן של האירוע. חותמת הזמן חייבת להיות מדויקת ותואמת לשעה שבה האירוע התרחש פיזית, ולא לשעה שבה הוא דווח.
מידע נוסף ודרישות נוספות לגבי דיווח על אירועי חיישנים עם זמן אחזור מקסימלי של דיווח שאינו אפס זמינים במאמר אוסף נתונים.
הפעלת חיישנים
ה-framework מפעיל ומשבית חיישנים באמצעות הפונקציה activate()
.
לפני שמפעילים חיישן, צריך להגדיר אותו באמצעות batch()
.
לאחר השבתת החיישן, אין לכתוב ל-Event FMQ אירועי חיישן נוספים מאותו חיישן.
חיישני שטיפה
אם החיישן מוגדר לאצוות של נתוני חיישנים, ה-framework יכול לאלץ הרצה מיידית של אירועי חיישנים שמקובצים באצווה באמצעות קריאה ל-flush()
. כתוצאה מכך, אירועי החיישן שנצברו בקבוצה עבור ה-handle של החיישן שצוין נכתבים באופן מיידי ב-Event FMQ. HAL של החיישנים חייב לצרף אירוע של סיום שטיפה לסוף אירועי החיישנים שנכתבים כתוצאה מהקריאה ל-flush()
.
הניקוי מתבצע באופן אסינכרוני (כלומר, הפונקציה חייבת לחזור באופן מיידי). אם ההטמעה משתמשת ב-FIFO יחיד למספר חיישנים, ה-FIFO הזה יתרוקן והאירוע 'סיום הריקון' יתווסף רק לחיישן שצוין.
אם בחיישן שצוין אין FIFO (אין אפשרות אגירת נתונים), או אם ה-FIFO היה ריק בזמן השיחה, flush()
עדיין צריך להצליח ולשלוח אירוע ריקון עבור החיישן. הכלל הזה חל על כל החיישנים, מלבד חיישנים מסוג 'צילום אחד'.
אם flush()
נקרא לחיישן של זריקה אחת, flush()
חייב להחזיר את הערך BAD_VALUE
ולא ליצור אירוע של סיום שטיפה.
כתיבת אירועי חיישנים ב-FMQ
טכנולוגיית FMQ לאירועים משמשת את חיישני HAL כדי לדחוף אירועי חיישנים אל המסגרת של החיישן ב-Android.
ה-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 של Sensors AIDL תומך גם ב-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, HAL של החיישנים צריך לאבטח את נעילת ההתעוררות כדי לוודא שהמערכת תישאר במצב פעיל עד שהמסגרת תוכל לטפל באירוע. לאחר קבלת אירוע WAKE_UP
, ה-framework מאבטח נעילה מצב שינה משלו, וכך מאפשר לחיישן HAL לשחרר את ה-wake Lock. כדי לסנכרן את האירוע שבו ה-HAL של החיישנים משחרר את נעילת ההתעוררות, משתמשים ב-Wake Lock FMQ.
HAL של החיישנים צריך לקרוא את FMQ של Wake Lock כדי לקבוע את מספר האירועים מסוג WAKE_UP
שהמסגרת טיפלה בהם. ה-HAL צריך לשחרר את נעילת ההתעוררות שלו רק לאירועי WAKE_UP
אם המספר הכולל של אירועי WAKE_UP
שלא טופלו הוא אפס.
אחרי הטיפול באירועי חיישנים, המסגרת סופרת את מספר האירועים שמסומנים כאירועי WAKE_UP
ומזינה את המספר הזה בחזרה ל-FMQ של Wake Lock.
המסגרת מגדירה את ההתראה WakeLockQueueFlagBits::DATA_WRITTEN
על הכתיבה ב-Wake Lock FMQ בכל פעם שהיא כותבת נתונים ב-Wake Lock FMQ.
חיישנים דינמיים
חיישנים דינמיים הם חיישנים שלא נמצאים פיזית במכשיר, אבל אפשר להשתמש בהם כקלט למכשיר, כמו גיימפאד עם מד תאוצה.
כשמחוברים חיישן דינמי, הפונקציה onDynamicSensorConnected
ב-ISensorsCallback
צריכה להיקרא HAL של החיישנים. כך המערכת תודיע למסגרת על החיישן הדינמי החדש, ותאפשר לשלוט בחיישן דרך המסגרת ולאפשר ללקוחות לצרוך את האירועים של החיישן.
באופן דומה, כשחיישן דינמי מנותק, צריך להפעיל את הפונקציה onDynamicSensorDisconnected
ב-ISensorsCallback
כדי שהמסגרת תוכל להסיר כל חיישן שלא זמין יותר.
ערוץ ישיר
ערוץ ישיר הוא שיטת פעולה שבה אירועי חיישנים נכתבים בזיכרון ספציפי במקום ב-FMQ של האירוע שעוקפים את מסגרת החיישנים של Android. לקוח שמירשם ערוץ ישיר צריך לקרוא את אירועי החיישן ישירות מהזיכרון ששימש ליצירת הערוץ הישיר, ולא יקבל את אירועי החיישן דרך המסגרת. הפונקציה configDirectReport()
דומה לפונקציה batch()
במצב עבודה רגיל, והיא קובעת את ערוץ הדיווח הישיר.
הפונקציות registerDirectChannel()
ו-unregisterDirectChannel()
יוצרות או משמידות שיחה ישירה חדשה.
מצבי הפעולה
הפונקציה setOperationMode()
מאפשרת למסגרת להגדיר חיישן כדי שהיא תוכל להחדיר נתוני חיישן לתוך החיישן. האפשרות הזו שימושית לבדיקה, במיוחד של אלגוריתמים שנמצאים מתחת למסגרת.
בדרך כלל משתמשים בפונקציה injectSensorData()
כדי לדחוף פרמטרים תפעוליים ל-HAL של החיישנים. אפשר גם להשתמש בפונקציה כדי להחדיר אירועי חיישן לחיישן ספציפי.
אימות
כדי לאמת את ההטמעה של Sensors HAL, מריצים את הבדיקות 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 של HAL של Sensors AIDL נמצאות ב-hardware/interfaces/sensors/aidl/vts/.
הבדיקות האלה מבטיחות שה-HAL של החיישנים מוטמע כראוי ושכל הדרישות ב-ISensors.aidl
וב-ISensorsCallback.aidl
מתקיימות.
אתחול ה-HAL
כדי ליצור ערוצי FMQ בין ה-framework ל-HAL, צריך לתמוך בפונקציה initialize()
.
חשיפת החיישנים הזמינים
ב-HAL של Sensors AIDL, הפונקציה getSensorsList()
חייבת להחזיר את אותו ערך במהלך הפעלה יחידה של המכשיר, גם במהלך הפעלות מחדש של HAL של Sensors. דרישה חדשה לפונקציה getSensorsList()
היא שהיא חייבת להחזיר את אותו ערך במהלך הפעלה של מכשיר יחיד, גם במהלך הפעלות מחדש של Sensors HAL. כך המערכת תוכל לנסות ליצור מחדש את החיבורים לחיישנים אם שרת המערכת יופעל מחדש. הערך שמוחזר על ידי getSensorsList()
יכול להשתנות אחרי שהמכשיר מופעל מחדש.
כתיבת אירועי חיישנים ב-FMQ
במקום להמתין לקריאה ל-poll()
, ב-HAL של Sensors AIDL, ה-HAL של Sensors חייב לכתוב באופן יזום אירועי חיישנים ל-Event FMQ בכל פעם שאירועי חיישנים זמינים. ה-HAL אחראי גם לכתוב את הביטים הנכונים ל-EventFlag
כדי לגרום לקריאה של FMQ בתוך המסגרת.
אירועי WAKE_UP
ב-Sensors HAL 1.0, ה-HAL יכול היה לשחרר את נעילת ההתעוררות שלו לכל אירוע WAKE_UP
בכל קריאה חוזרת ל-poll()
אחרי ש-WAKE_UP
פורסם ב-poll()
, כי הדבר סימן שהמסגרת עיבד את כל אירועי החיישן וקיבל נעילת התעוררות, אם היה צורך. מכיוון שב-HAL של Sensors AIDL, ה-HAL כבר לא מקבל התראה כשהמסגרת מעבדת אירועים שנכתבו ב-FMQ, ה-FMQ של Wake Lock מאפשר למסגרת לתקשר עם ה-HAL כשהיא מטפלת באירועי WAKE_UP
.
ב-HAL של Sensors AIDL, נעילת ההתעוררות שמאובטחת על ידי ה-HAL של Sensors לאירועים מסוג WAKE_UP
חייבת להתחיל ב-SensorsHAL_WAKEUP
.
חיישנים דינמיים
חיישנים דינמיים הוחזרו באמצעות הפונקציה poll()
ב-Sensors HAL 1.0.
ב-Sensors AIDL HAL נדרש לקרוא ל-onDynamicSensorsConnected
ול-onDynamicSensorsDisconnected
ב-ISensorsCallback
בכל פעם שמתרחשים שינויים בחיבורים הדינמיים של החיישנים. פונקציות הקריאה החוזרת האלה זמינות כחלק מהצבען ISensorsCallback
שסופק באמצעות הפונקציה initialize()
.
מצבי הפעולה
חייבת להיות תמיכה במצב DATA_INJECTION
לחיישנים מסוג WAKE_UP
.
תמיכה במספר ממשקי HAL
HAL של Sensors AIDL תומך ב-multi-HAL באמצעות המסגרת של Sensors Multi-HAL. פרטי ההטמעה מפורטים במאמר העברה מ-Sensors HAL 2.1.