חיישנים עם מולטי HAL

‏Sensors Multi-HAL הוא מסגרת שמאפשרת ל-HAL של חיישנים לפעול לצד HAL של חיישנים אחרים. ‏Sensors Multi-HAL טוען באופן דינמי HAL משני של חיישנים שנשמרים כספריות דינמיות במחיצה של הספק, ומספק להם אובייקט קריאה חוזרת (callback) שיכול לטפל בפרסום אירועים ובקבלה וביטול של נעילת ההתעוררות. HAL משני של חיישנים הוא HAL של חיישנים שמוטמע באובייקט משותף במחיצה של הספק, והוא משמש את המסגרת של HAL מרובה. רכיבי ה-HAL המשניים האלה לא תלויים זה בזה או בקוד ה-HAL המורכב שמכיל את הפונקציה הראשית של התהליך.

‏Sensors Multi-HAL 2.1, שזמין במכשירים עם Android מגרסה 11 ואילך, הוא גרסה משופרת של Sensors Multi-HAL 2.0 שתומכת בחיבור של ממשקי HAL משניים שיכולים לחשוף את סוג החיישן של זווית הציר. כדי לתמוך בסוג החיישן הזה, ב-Sub-HAL צריך להשתמש בממשקי Sub-HAL API מוגדר בתוך 2.1 כותרת SubHal.

במכשירים עם Android מגרסה 13 ואילך שמשתמשים ב-Sensors AIDL HAL, אפשר להשתמש בשכבת shim עם תמיכה במספר HAL כדי לאפשר יכולת של מספר HAL. פרטי ההטמעה מפורטים במאמר שימוש ב-Sensors Multi-HAL עם Sensors AIDL HAL.

ההבדל בין חיישנים Multi-HAL 2 לחיישנים HAL 2

חיישנים Multi-HAL 2, זמינים במכשירים עם מערכת Android 10 ומעלה, מציג כמה פשטות בנוסף לחיישן HAL של חיישנים 2 שיהיה לכם קל יותר לאינטראקציה עם ממשקי API עם HAL. התכונה 'חיישנים Multi-HAL 2' מציגה שרת ה-HalProxy לטיפול בהטמעה של ממשק החיישנים HAL 2 V2_1/SubHal (או V2_0/SubHal) שמאפשר ל-HalProxy לקיים אינטראקציה עם רכיבי משנה של HAL.

הממשק של ISensorsSubHal שונה 2.1/ISensors.hal (או 2.0/ISensors.hal) משתמש בדרכים הבאות:

  • שיטת initialize מעבירה את הכיתה IHalProxyCallback במקום שני FMQ ו-ISensorsCallback.
  • ב-HAL משניים צריך להטמיע פונקציית ניפוי באגים כדי לספק מידע על ניפוי הבאגים בדוחות הבאגים.
  • יש להטמיע פונקציית שם ב-HAL משני כדי שאפשר יהיה להבדיל בין ה-HAL המשני שנטען לבין HAL משני אחר.

ההבדל העיקרי בין Sensors Multi-HAL 2 לבין Sensors HAL 2 הוא בפונקציות ההפעלה. במקום לספק ערוצי FMQ, IHalProxyCallback הממשק מספק שתי שיטות – אחת לפרסום אירועי חיישנים בחיישנים ושיטה אחת ליצירת חסימות מצב שינה. מתחת לפני השטח, ה-Multi-HAL של חיישנים מנהל את כל האינטראקציות עם ה-FMQ כדי להבטיח העברה בזמן של אירועי חיישנים לכל ה-HAL המשניים. מומלץ מאוד שכלי משנה ל-HAL ישתמשו שיטה createScopedWakelock להאציל את הנטל של תזמון חסימות מצב שינה אל באמצעות החיישנים עם מולטי HAL, וניתן לרכז את השימוש בחסימות מצב שינה באמצעות התכונה 'נעילת מצב שינה' משותפת לחיישן Multi-HAL כולו, שמצמצם שיחות נעילה וביטול נעילה.

ב-Sensors Multi-HAL 2 יש גם כמה תכונות בטיחות מובנות. הוא מטפל מצבים שבהם החיישן FMQ מלא או מסגרת החיישן של Android מופעלת מחדש וצריך לאפס את מצב החיישן. בנוסף, כשהאירועים פורסמה בכיתה HalProxy, אבל מסגרת החיישן לא יכולה לקבל את האירועים באופן מיידי, באמצעות החיישנים Multi-HAL יש אפשרות להעביר את האירועים לרקע כדי לאפשר לעבודה להמשיך בכל משימות המשנה במהלך המתנה אירועים שיתפרסמו.

קוד מקור והטמעת הפניה

הקוד של All Sensors Multi-HAL זמין ב-hardware/interfaces/sensors/common/default/2.X/multihal/. בהמשך מופיעות כמה קישורים למקורות מידע.

  • HalProxy.h: האובייקט HalProxy נוצר באמצעות חיישנים מרובי-HAL ומטפל העברת נתונים מתת-ה-HAL למסגרת החיישן.
  • HalProxy.cpp: ההטמעה של HalProxy מכילה את כל הלוגיקה הנדרשת למולטיפלקס של התקשורת בין ממשקי HAL משניים לבין מסגרת החיישן.
  • SubHal.h: הממשק ISensorsSubHal מגדיר את הממשק ש-HAL משניים חייבים לפעול לפיו כדי להיות תואם ל-HalProxy. ה-HAL המשני מטמיע את השיטה initialize כדי שאפשר יהיה להשתמש באובייקט HalProxyCallback עבור postEvents ו-createScopedWakelock.

    להטמעות של Multi-HAL 2.0, צריך להשתמש בגרסה 2.0 של SubHal.h

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: בדיקות היחידות האלה מאמתות את ההטמעה של HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: בדוגמה הזו להטמעת תת-HAL נעשה שימוש בחיישנים מזויפים כדי ליצור נתונים מזויפים. שימושי לבדיקת האינטראקציה בין מספר HAL משניים במכשיר.

הטמעה

בקטע הזה מתואר איך להטמיע חיישנים Multi-HAL בסעיפים הבאים מצבים:

שימוש ב-Sensors Multi-HAL עם Sensors AIDL HAL

כדי לאפשר יכולת של HAL מרובה עם HAL של Sensors AIDL, מייבאים את מודול שכבת השימ של AIDL Multi-HAL שנמצא ב-hardware/interfaces/sensors/aidl/default/multihal/. המודול מטפל בהמרה שבין חיישני AIDL ו-HIDL להגדרות HAL ומגדיר wrapper במסגרת ממשק ריבוי HAL שמתואר הטמעת חיישנים Multi-HAL 2.1. שכבת השימ של AIDL עם תמיכה במספר ממשקי HAL תואמת למכשירים שמטמיעים את Sensors Multi-HAL 2.1.

שכבת השימ (shim) של AIDL עם מספר HAL מאפשרת לחשוף את סוגים של מכשיר מעקב אחר תנועות הראש וחיישן IMU עם צירים מוגבלים ב-HAL של Sensors AIDL. כדי להשתמש בחיישנים האלה שמוגדרים על ידי ממשק AIDL HAL, מגדירים את השדה type מבני SensorInfo בהטמעה של getSensorsList_2_1(). זה בטוח כי השדות של סוג החיישן עם גיבוי שלם של חיישני AIDL ו-HIDL לא חופפות.

הטמעת Sensors Multi-HAL 2.1

כדי להטמיע את Sensors Multi-HAL 2.1 במכשיר חדש, פועלים לפי השלבים הבאים:

  1. הטמעת הממשק של ISensorsSubHal כפי שמתואר ב SubHal.h.
  2. ליישם את sensorsHalGetSubHal_2_1 ב-SubHal.h.
  3. מוסיפים יעד cc_library_shared כדי ליצור את תת-ה-HAL שהוטמע לאחרונה. כשמוסיפים את היעד:

    1. מוודאים שהיעד נדחף למקום כלשהו בספק למחיצה של המכשיר.
    2. בקובץ התצורה שנמצא בכתובת /vendor/etc/sensors/hals.conf, מוסיפים את הנתיב לספרייה בשורה חדשה. אם צריך, יוצרים את הקובץ hals.conf.

    לדוגמה של רשומה Android.bp ליצירת ספריית HAL משנית, ראו hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. מסירים את כל הרשומות של android.hardware.sensors מהקובץ manifest.xml, שמכיל את רשימת ה-HAL הנתמכים במכשיר.

  5. הסרת כל שירות android.hardware.sensors ו-service.rc קבצים מ- את הקובץ device.mk ומוסיפים את android.hardware.sensors@2.1-service.multihal ו-android.hardware.sensors@2.1-service.multihal.rc עד PRODUCT_PACKAGES.

בזמן האתחול, HalProxy מתחיל, מחפש את תת-ה-HAL החדש שהוטמע, מאתחל אותו באמצעות קריאה sensorsHalGetSubHal_2_1.

העברה מ-Sensors Multi-HAL 2.0 ל-Multi-HAL 2.1

כדי להעביר מ-Multi-HAL 2.0 ל-Multi-HAL 2.1, מטמיעים את הממשק SubHal ומרכיבים מחדש את ה-HAL המשני.

אלה ההבדלים בין הממשק של SubHal בגרסה 2.0 ובגרסה 2.1:

  • ב-IHalProxyCallback נעשה שימוש בסוגי הנתונים שנוצרו בגרסה 2.1 של מפרט ISensors.hal.
  • הפונקציה initialize() מעבירה IHalProxyCallback חדש במקום זה שממשק SubHal 2.0 מעביר
  • רכיבי Sub-HAL חייבים להטמיע את getSensorsList_2_1 ואת injectSensorData_2_1 במקום ב-getSensorsList וב-injectSensorData, כי השיטות האלה עושות שימוש הסוגים החדשים שנוספו בגרסה 2.1 של המפרט ISensors.hal.
  • כדי ש-Multi-HAL יתייחס ל-HAL משניים כ-HAL משני בגרסה 2.1, הוא צריך לחשוף את sensorsHalGetSubHal_2_1 במקום את sensorsHalGetSubHal.

יציאה מ-Sensors HAL 2.0

כשמשדרגים ל-Sensors Multi-HAL 2.0 מ-Sensors HAL 2.0, חשוב לוודא שההטמעה של HAL עומדת בדרישות הבאות.

אתחול ה-HAL

לחיישנים HAL 2.0 יש פונקציה אתחול שמאפשרת לשירות החיישן העברת אותות FMQ וקריאה חוזרת (callback) של חיישן דינמי. ב-Sensors Multi-HAL 2.0, הפונקציה initialize() מעבירה קריאה חוזרת אחת שצריך להשתמש בה כדי לפרסם אירועי חיישנים, לקבל נעילת התעוררות ולהודיע על חיבורים ודילוגים דינמיים של חיישנים.

פרסום אירועי חיישנים להטמעת Multi-HAL

במקום לפרסם אירועי חיישנים דרך FMQ, תת-HAL צריך לכתוב אירועי חיישנים ב-IHalProxyCallback כשאירועי חיישנים זמינים.

אירועי WAKE_UP

ב-Sensors HAL 2.0, ה-HAL יכול לנהל את נעילת ההתעוררות להטמעה שלו. ב-Sensors Multi-HAL 2.0, ממשקי ה-HAL המשניים מאפשרים להטמעת ה-Multi-HAL לנהל את חסימות מצב השינה, והם יכולים לבקש חסימה של מצב השינה באמצעות קריאה ל-createScopedWakelock. יש לרכוש חסימת מצב שינה בהיקף נעול ולהעביר אותה אל postEvents כאשר פרסום אירועי יציאה ממצב שינה בהטמעה של Multi-HAL.

חיישנים דינמיים

לחיישנים Multi-HAL 2.0 נדרשת התאמה של onDynamicSensorsConnected ושל onDynamicSensorsDisconnected אינץ' IHalProxyCallback מופעלות בכל פעם שחיבורי החיישנים הדינמיים משתנים. הקריאות החוזרות האלה זמין כחלק מהסמן IHalProxyCallback שמסופק את הפונקציה initialize().

יציאה מ-Sensors HAL 1.0

כשמשדרגים ל-Sensors Multi-HAL 2.0 מ-Sensors HAL 1.0, חשוב לוודא שההטמעה של HAL עומדת בדרישות הבאות.

אתחול HAL

צריך לתמוך בפונקציה initialize() כדי ליצור את הקריאה החוזרת (callback) הטמעת Sub-HAL והטמעת Multi-HAL.

חשיפת החיישנים הזמינים

ב-Sensors Multi-HAL 2.0, הפונקציה getSensorsList() חייבת להחזיר את אותו ערך במהלך הפעלה יחידה של המכשיר, גם במהלך הפעלות מחדש של HAL של חיישנים. כך אפשר המסגרת בניסיון ליצור מחדש חיבורי חיישן, אם שרת המערכת מופעלת מחדש. הערך שמוחזר על ידי getSensorsList() יכול להשתנות אחרי שהמכשיר מבצע הפעלה מחדש.

פרסום אירועים של חיישנים בהטמעת Multi-HAL

ב-Sensors HAL 2.0, במקום להמתין לקריאה ל-poll(), ה-HAL המשני צריך לכתוב באופן יזום אירועי חיישנים ב-IHalProxyCallback בכל פעם שאירועי חיישנים זמינים.

אירועי WAKE_UP

בחיישן HAL 1.0, מדד HAL יכול לנהל את התכונה 'נעילת מצב שינה' לצורך הטמעה. ב-Sensors Multi-HAL 2.0, ממשקי ה-HAL המשניים מאפשרים להטמעת ה-Multi-HAL לנהל את החסימות של מצב השינה, והם יכולים לבקש חסימה של מצב השינה באמצעות קריאה ל-createScopedWakelock. צריך לקבל ולשלוח ל-postEvents מנעול התעוררות ברמת הנעילה כשמפרסמים אירועי התעוררות להטמעת Multi-HAL.

חיישנים דינמיים

בחיישן HAL 1.0, החיישנים הדינמיים מוחזרים דרך הפונקציה poll(). ב-Sensors Multi-HAL 2.0 נדרש לקרוא לפונקציות onDynamicSensorsConnected ו-onDynamicSensorsDisconnected ב-IHalProxyCallback בכל פעם שמתבצע שינוי בחיבורי החיישנים הדינמיים. פונקציות הקריאה החוזרת האלה זמינות כחלק מהצבען IHalProxyCallback שסופק באמצעות הפונקציה initialize().

יציאה מחיישנים Multi-HAL 1.0

כדי לנייד הטמעה קיימת מ: Sensors Multi-HAL 1.0, יש לבצע את השלבים הבאים.

  1. מוודאים שהגדרת ה-HAL של החיישנים נמצאת ב-/vendor/etc/sensors/hals.conf. יכול להיות שתצטרכו להעביר את הקובץ שנמצא ב-/system/etc/sensors/hals.conf.
  2. צריך להסיר את כל ההפניות אל hardware/hardware.h וגם hardware/sensors.h מכשירים כאלה לא נתמכים ב-HAL 2.0.
  3. שקעי משנה של יציאות כפי שמתואר במאמר ניוד מחיישנים עם האלר 1.0.
  4. מגדירים את Sensors Multi-HAL 2.0 כ-HAL הייעודי לפי השלבים 3 ו-4 בקטע הטמעת Sensors Mutli-HAL 2.0.

אימות

הפעלת VTS

אחרי שמשלבים HAL משני אחד או יותר עם Sensors Multi-Hal 2.1, אפשר להשתמש ב-Vendor Test Suite‏ (VTS) כדי לוודא שהטמעות ה-HAL המשניים עומדות בכל הדרישות שהוגדרו בממשק ה-HAL של Sensors.

כדי להריץ רק את בדיקות ה-VTS של החיישנים כש-VTS מוגדר במכונה המארחת, מריצים את הפקודות הבאות:

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

אם מפעילים את שכבת AIDL Multi-HAL shim, מריצים את VtsAidlHalSensorsTargetTest.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

הרצת בדיקות יחידה

בדיקות היחידה ב-HalProxy_test.cpp בודקות את HalProxy באמצעות HAL משניים מזויפים שנוצרים בבדיקה היחידה ולא נטענים באופן דינמי. כשיוצרים בדיקות משנה חדשות כדי לוודא שגרסת המשנה החדשה של ה-HAL הוטמעה כראוי.

כדי להריץ את הבדיקות, מריצים את הפקודות הבאות:

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

בדיקה באמצעות תהליכי משנה מזויפים

ממשקי ה-HAL המשניים המזויפים הם הטמעות דמה של ממשק ISensorsSubHal. ממשקי ה-HAL המשניים חושפים רשימות שונות של חיישנים. כשהחיישנים מופעלים, הם מפרסמים מדי פעם אירועי חיישנים שנוצרו באופן אוטומטי ב-HalProxy מבוסס על המרווחים שמצוינים בבקשת חיישן נתונה.

אפשר להשתמש ב-Sub-HAL המזויפים כדי לבדוק איך קוד Multi-HAL המלא פועל עם תת-נושאים אחרים שנטענות במערכת וכדי להדגיש היבטים שונים של קוד Multi-HAL מחיישנים.

שני HAL משניים מזויפים זמינים בכתובת hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

כדי ליצור ולדחוף הודעות משנה מזויפות למכשיר, מבצעים את השלבים הבאים:

  1. מריצים את הפקודות הבאות כדי ליצור את שלוש גרסת ה-HAL המשניות המזויפות ולשלוח אותן למכשיר:

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  2. מעדכנים את הגדרת ה-HAL של החיישנים ב-/vendor/etc/sensors/hals.conf עם הנתיבים של ה-HAL המשניים המזויפים.

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. מפעילים מחדש את HalProxy וטעונים את שכבות ה-HAL המשניות החדשות שמפורטות בקובץ התצורה.

    adb shell stop
    adb shell start
    

ניפוי באגים

מפתחים יכולים לנפות באגים ב-framework באמצעות הפקודה lshal. כדי לבקש את הפלט של ניפוי הבאגים של HAL של החיישנים, מריצים את הפקודה הבאה:

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

לאחר מכן, המידע על המצב הנוכחי של HalProxy ו-HALs שלו פלט לטרמינל. למטה תוכלו לראות דוגמה לפלט של הפקודה אובייקט HalProxy ומזהי משנה מזויפים.

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

אם המספר שצוין עבור # of events on pending write queue הוא מספר גדול (1,000 או יותר), המשמעות היא שיש הרבה אירועים בהמתנה לכתיבה למסגרת החיישנים. המשמעות היא ששירות החיישן נמצא במצב נעילה הדדית או קרס ולא מעבד אירועי חיישנים, או שקבוצה גדולה של אירועי חיישנים פורסמה לאחרונה מ-HAL משני.

אם מספר ההפניות של נעילת ההתעוררות גדול מ-0, סימן ש-HalProxy צבר נעילת התעוררות. הערך צריך להיות גדול מ-0 רק אם ScopedWakelock מתבצע במכוון, או אם אירועי התעוררות נשלחו אל HalProxy לא עבר עיבוד על ידי מסגרת החיישן.

מתאר הקובץ שמוענק לשיטת ניפוי הבאגים של HalProxy מועבר לכל HAL משני, ולכן המפתחים צריכים להטמיע את שיטת ניפוי הבאגים כחלק מהממשק ISensorsSubHal.