Sensors Multi-HAL

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

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

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

ההבדל בין Sensors Multi-HAL 2 לבין Sensors HAL 2

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

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

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

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

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

קוד מקור ויישום לדוגמה

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

  • HalProxy.h: האובייקט HalProxy נוצר על ידי Sensors multi-HAL ומטפל בהעברת נתונים מ-sub-HALs אל מסגרת החיישנים.
  • HalProxy.cpp: ההטמעה של HalProxy מכילה את כל הלוגיקה שנדרשת כדי לבצע ריבוב של תקשורת בין רכיבי משנה של HAL לבין מסגרת החיישן.
  • SubHal.h: ממשק ISensorsSubHal מגדיר את הממשק שחייבים לפעול לפיו ב-sub-HAL כדי להיות תואם ל-HalProxy. ה-sub-HAL מטמיע את שיטת האתחול כדי שאפשר יהיה להשתמש באובייקט 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/: הטמעה לדוגמה של sub-HAL שמשתמשת בחיישנים מזויפים כדי ליצור נתונים מזויפים. האפשרות הזו שימושית לבדיקת האינטראקציה בין כמה רכיבי HAL משניים במכשיר.

הטמעה

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

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

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

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

הטמעה של Sensors Multi-HAL 2.1

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

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

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

    דוגמה לרשומה Android.bp ליצירת ספריית sub-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 מתחיל, מחפש את ה-sub-HAL החדש שהוטמע ומאתחל אותו על ידי קריאה ל-sensorsHalGetSubHal_2_1.

העברה של יציאה מ-Sensors Multi-HAL 2.0 ל-Multi-HAL 2.1

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

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

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

העברה מ-Sensors HAL 2.0

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

אתחול ה-HAL

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

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

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

אירועי WAKE_UP

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

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

ב-Sensors 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() כדי ליצור את הקריאה החוזרת בין ה-HAL המשני לבין הטמעת ה-Multi-HAL.

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

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

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

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

אירועי WAKE_UP

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

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

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

העברה מ-Sensors 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. מעבירים את קובצי המשנה של HAL כמו שמתואר במאמר העברה מ-Sensors Hal 1.0.
  4. מגדירים את Sensors Multi-HAL 2.0 כ-HAL ייעודי לפי שלבים 3 ו-4 בקטע הטמעה של Sensors Multi-HAL 2.0.

אימות

הפעלת VTS

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

כדי להריץ רק את בדיקות החיישנים של 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

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

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

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

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

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

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

בדיקה באמצעות רכיבי ה-HAL המזויפים

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

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

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

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

  1. מריצים את הפקודות הבאות כדי ליצור ולדחוף את שלושת רכיבי ה-sub-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

ניפוי באגים

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

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

המידע על המצב הנוכחי של HalProxy ושל רכיבי המשנה של HAL מוצג במסוף. בדוגמה הבאה מוצג פלט הפקודה עבור האובייקט HalProxy ורכיבי sub-HAL פיקטיביים.

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 או יותר), המשמעות היא שיש הרבה אירועים שממתינים לכתיבה למסגרת החיישנים. המשמעות היא ששירות החיישן נתקע או קרס ולא מעבד אירועים של חיישנים, או שקבוצה גדולה של אירועים של חיישנים פורסמה לאחרונה מ-sub-HAL.

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

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