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

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

חיישן Multi-HAL 2.1 זמין במכשירים עם Android מגרסה 11 ואילך, הוא איטרציה של חיישנים Multi-HAL 2.0 שתומך בטעינה של רכיבי HAL בטעינה שיכולים לחשוף את סוג החיישן של זווית הציר. כדי לתמוך בסוג החיישן הזה, ממשקי HAL משניים חייבים להשתמש בממשקי ה-API של HAL משני שמוגדרים בכותרת 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 ואילך, מוצגות כמה פשטות בנוסף ל-Sensors HAL 2 כדי להקל על האינטראקציה עם ממשקי API עם HAL. ב-Sensors Multi-HAL 2 מוצגת הכיתה HalProxy לטיפול בהטמעה של ממשק Sensors HAL 2 והממשק V2_1/SubHal (או V2_0/SubHal) כדי לאפשר ל-HalProxy לקיים אינטראקציה עם ממשקי HAL משניים.

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

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

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

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

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

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

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

הטמעה

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

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

כדי לאפשר יכולת של פעילות מולטי HAL באמצעות החיישנים AIDL HAL, צריך לייבא את מודול שכבת ה-AIDL Multi-HAL shim, שנמצא ב-hardware/interfaces/sensors/aidl/default/multihal/. המודול מטפל בהמרה בין סוגי ההגדרות של חיישנים ב-HAL של AIDL ו-HIDL, ומגדיר מעטפת סביב ממשק ה-HAL המורכב שמתואר במאמר הטמעת Sensors 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. מטמיעים את ה-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 חדש במקום זה שממשק SubHal 2.0 מעביר
  • רכיבי Sub-HAL חייבים להטמיע את getSensorsList_2_1 ואת injectSensorData_2_1 במקום את getSensorsList ואת injectSensorData, כי ב-methods האלה נעשה שימוש בסוגים החדשים שנוספו בגרסה 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) של חיישן דינמי. בחיישן Multi-HAL 2.0, הפונקציה initialize() מעבירה קריאה חוזרת (callback) יחידה שמשמשת לפרסום אירועים של חיישנים, לקבלת חסימות מצב שינה ולשליחת התראות לגבי חיבור וניתוקים דינמיים של החיישנים.

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

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

אירועי WAKE_UP

ב-Sensors 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().

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

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

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

אירועי WAKE_UP

ב-Sensors HAL 1.0, ה-HAL יכול לנהל את נעילת ההתעוררות להטמעה שלו. ב-Sensors Multi-HAL 2.0, ממשקי ה-HAL המשניים מאפשרים להטמעת ה-Multi-HAL לנהל את החסימות של מצב השינה, והם יכולים לבקש חסימה של מצב השינה באמצעות קריאה ל-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, על סמך המרווחים שצוינו בבקשה נתונה של חיישן.

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

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

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

  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

ניפוי באגים

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

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

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

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.