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

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

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

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

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

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

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

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

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

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

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

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

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

הטמעה

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

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

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

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

הטמעת חיישנים עם Multi-HAL 2.1

כדי להטמיע את החיישנים 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 ליצירה של ספריית משנה 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.

יציאה מחיישנים Multi-HAL 2.0 ל-Multi-HAL 2.1

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

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

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

יציאה מחיישנים HAL 2.0

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

אתחול HAL

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

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

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

אירועי WAKE_UP

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

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

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

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

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

אתחול HAL

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

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

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

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

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

אירועי WAKE_UP

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

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

בחיישן HAL 1.0, החיישנים הדינמיים מוחזרים דרך הפונקציה poll(). לחיישנים 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. שקעי משנה של יציאות כמו שמתואר במאמר ניוד מחיישנים עם Hal 1.0.
  4. פועלים לפי שלבים 3 ו-4 בסעיף הטמעת חיישנים Mutli-HAL 2.0 כדי להגדיר את Sensors Multi-HAL 2.0 כ-HAL הייעודי.

אימות

הפעלת VTS

אחרי שתשלבו תת-HAL אחד או יותר עם חיישנים Multi-Hal 2.1, תוכלו להשתמש בחבילת הבדיקה של הספק (VTS) כדי לוודא שהטמעות המשנה מסוג HAL עומדות בכל הדרישות של ממשק ה-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

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

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

הרצת בדיקות יחידה (unit testing)

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

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

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

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

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

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

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

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

  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 ולטעון את נושאי המשנה החדשים שמפורטים בהגדרה.

    adb shell stop
    adb shell start
    

ניפוי באגים

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

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

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

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

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