ארגון מחדש של RIL

ב-Android 7.0 בוצע רפקטורינג של שכבת ממשק הרדיו (RIL) באמצעות קבוצה של תכונות לשיפור הפונקציונליות של RIL. כדי להטמיע את התכונות האלה, שמומלצות אבל לא חובה, צריך לבצע שינויים בקוד של השותף. שינויים בשיטת refactoring תואמים לדורות קודמים, כך שהטמעות קודמות של התכונות שעברו refactoring ממשיכות לפעול.

השיפורים הבאים כלולים בשינוי המבנה של RIL:

  • קודי שגיאה של RIL מאפשר קודי שגיאה ספציפיים בנוסף לקוד GENERIC_FAILURE הקיים. המידע הזה עוזר לפתור בעיות שקשורות לשגיאות, כי הוא מספק פרטים ספציפיים יותר על הגורם לשגיאות.
  • ניהול גרסאות של RIL. מספק מידע מדויק יותר על הגרסה וקל יותר להגדרה.
  • תקשורת RIL באמצעות נעילות השכמה. משפר את ביצועי הסוללה של המכשיר.

אתם יכולים להטמיע את כל השיפורים שצוינו למעלה או רק חלק מהם. פרטים נוספים זמינים בהערות על קוד בנושא ניהול גרסאות של RIL ב-https://android.googlesource.com/platform/hardware/ril/+/android16-qpr2-release/include/telephony/ril.h.

הטמעה של קודי שגיאה משופרים של RIL

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

ב-Android מגרסה 7.x ואילך, יצרני ציוד מקורי (OEM) יכולים להחזיר ערך קוד שגיאה נפרד שמשויך לכל שגיאה שסווגה כרגע כ-GENERIC_FAILURE. יצרני ציוד מקורי שלא רוצים לחשוף לציבור את קודי השגיאה המותאמים אישית שלהם יכולים להחזיר שגיאות כקבוצה נפרדת של מספרים שלמים (למשל 1 עד x) שממופים כ-OEM_ERROR_1 עד OEM_ERROR_X. הספקים צריכים לוודא שכל קוד שגיאה מוסווה שמוחזר ממופה לסיבת שגיאה ייחודית בקוד. שימוש בקודי שגיאה ספציפיים יכול לזרז את ניפוי הבאגים ב-RIL בכל פעם שקודי שגיאה כלליים מוחזרים על ידי יצרן ציוד מקורי (OEM), כי לעיתים קרובות לוקח יותר מדי זמן לזהות את הסיבה המדויקת לקוד שגיאה GENERIC_FAILURE (ולפעמים אי אפשר לגלות אותה).

בנוסף, ril.h מוסיף עוד קודי שגיאה לסוגי הנתונים המנויים RIL_LastCallFailCause ו-RIL_DataCallFailCause, כדי שקוד הספק יוכל להימנע מהחזרת שגיאות כלליות כמו CALL_FAIL_ERROR_UNSPECIFIED ו-PDP_FAIL_ERROR_UNSPECIFIED.

אימות של קודי שגיאה משופרים ב-RIL

אחרי שמוסיפים קודי שגיאה חדשים במקום הקוד GENERIC_FAILURE צריך לוודא שקודי השגיאה החדשים מוחזרים על ידי קריאת ה-RIL במקום GENERIC_FAILURE.

הטמעה של ניהול גרסאות משופר של RIL

היו בעיות בניהול הגרסאות של RIL בגרסאות ישנות של Android: הגרסה עצמה לא הייתה מדויקת, המנגנון לדיווח על גרסת RIL לא היה ברור (מה שגרם לספקים מסוימים לדווח על גרסה שגויה), והפתרון העקיף להערכת הגרסה היה מועד לטעויות.

ב-Android 7.x ואילך, במסמך ril.h מפורטים כל ערכי הגרסה של RIL, מתוארת גרסת ה-RIL המתאימה ומופיעים כל השינויים שבוצעו בגרסה הזו. כשמבצעים שינויים שמתאימים לגרסת RIL, הספקים צריכים לעדכן את הגרסה שלהם בקוד ולהחזיר את הגרסה הזו ב-RIL_REGISTER.

אימות של גרסאות משופרות של RIL

צריך לוודא שגרסת ה-RIL שתואמת לקוד ה-RIL מוחזרת במהלך RIL_REGISTER (ולא RIL_VERSION שמוגדר ב-ril.h).

הטמעה של תקשורת RIL באמצעות wakelocks

נעשה שימוש ב-wakelocks מתוזמנים בתקשורת RIL בצורה לא מדויקת, מה שמשפיע לרעה על ביצועי הסוללה. ב-Android 7.x ומעלה, אפשר לשפר את הביצועים על ידי סיווג של בקשות RIL ועדכון הקוד כדי לטפל ב-wakelocks באופן שונה עבור סוגים שונים של בקשות.

סיווג בקשות RIL

בקשות RIL יכולות להיות מוזמנות או לא מוזמנות. ספקים צריכים לסווג בקשות שנשלחו אליהם כאחת מהאפשרויות הבאות:

  • synchronous. בקשות שלא דורשות זמן רב לתגובה. לדוגמה, RIL_REQUEST_GET_SIM_STATUS.
  • asynchronous. בקשות שלוקח הרבה זמן לקבל עליהן תשובה. לדוגמה, RIL_REQUEST_QUERY_AVAILABLE_NETWORKS.

בקשות RIL אסינכרוניות שמתקבלות בתגובה לבקשה יכולות לקחת זמן רב. אחרי קבלת אישור מקוד הספק, RIL Java מבטל את חסימת מצב השינה, מה שעלול לגרום למעבד האפליקציה לעבור ממצב המתנה למצב השהיה. כשהתגובה זמינה מקוד הספק, RIL Java (מעבד האפליקציה) מקבל מחדש את ה-wakelock, מעבד את התגובה ואז חוזר למצב המתנה. מעבר ממצב לא פעיל למצב שינה וחזרה למצב לא פעיל עלול לצרוך הרבה חשמל.

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

תרחישי תקשורת של RIL

בתרשימים הבאים מוצגים תרחישי תקשורת נפוצים של RIL, ומוצעים פתרונות לשינוי קוד כדי לטפל בבקשות RIL שמתקבלות בתגובה לבקשה ובבקשות RIL שמתקבלות ללא בקשה.

הערה: פרטים על ההטמעה של הפונקציות שמופיעות בתרשימים הבאים מפורטים בשיטות acquireWakeLock(),‏ decrementWakeLock() ו-clearWakeLock( ב-ril.cpp.

תרחיש: בקשת RIL ותגובה אסינכרונית שמתקבלת לאחר בקשה

בתרחיש הזה, אם התגובה המבוקשת של RIL צפויה להימשך זמן רב (כלומר, תגובה ל-RIL_REQUEST_GET_AVAILABLE_NETWORKS), נעילת ההשכמה נמשכת זמן רב בצד של מעבד האפליקציה. בעיות במודם יכולות גם לגרום להמתנה ארוכה.

איור 1. RIL solicited asynchronous response.

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

איור 2. ‫Wakelock מוחזק על ידי המודם.
  1. בקשת RIL נשלחת והמודם מקבל נעילת השכמה כדי לעבד את הבקשה.
  2. המודם שולח אישור שגורם לצד של Java להקטין את מונה ה-wakelock ולשחרר אותו כשערך המונה הוא 0.

    הערה: משך הזמן הקצוב לתפוס את המעבד במצב פעיל (wakelock) עבור רצף בקשת האישור יהיה קצר יותר ממשך הזמן הקצוב שמשמש כרגע, כי האישור אמור להתקבל די מהר.

  3. אחרי עיבוד הבקשה, המודם שולח הפרעה לקוד הספק שמקבל את ה-wakelock ושולח תגובה ל-ril.cpp, שבתורו מקבל את ה-wakelock ושולח תגובה לצד Java.
  4. כשהתגובה מגיעה לצד של Java, מתבצעת השגת נעילת השכמה ומוחזרת תגובה למתקשר.
  5. אחרי שכל המודולים מעבדים את התגובה, נשלח אישור (דרך socket) בחזרה אל ril.cpp, ואז מבוטל נעילת המכשיר שהופעלה בשלב 3.

פתרון 2: המודם לא מחזיק את ה-wakelock והתגובה מהירה (בקשת RIL ותגובה סינכרוניות). ההתנהגות הסינכרונית לעומת האסינכרונית מוצפנת בפקודת RIL ספציפית ונקבעת על בסיס כל שיחה.

איור 3. ה-Wakelock לא מוחזק על ידי המודם.
  1. בקשת RIL נשלחת על ידי קריאה ל-acquireWakeLock() בצד Java.
  2. קוד הספק לא צריך לקבל נעילת השכמה, והוא יכול לעבד את הבקשה ולהגיב במהירות.
  3. כשמתקבלת התגובה בצד של Java, מתבצעת קריאה לפונקציה decrementWakeLock(), שמקטינה את מונה ה-wakelock ומשחררת את ה-wakelock אם ערך המונה הוא 0.

תרחיש: תגובה לא רצויה של RIL

בתרחיש הזה, לתגובות לא רצויות של RIL יש דגל מסוג wakelock ב- שהמציין אם צריך להשיג wakelock לתגובת הספק. אם הדגל מוגדר, מוגדרת נעילת השכמה מתוזמנת והתגובה נשלחת דרך שקע לצד Java. כשהטיימר מסתיים, נעילת ההשכמה משתחררת. יכול להיות שמשך הזמן של ה-wakelock יהיה ארוך או קצר מדי לתגובות שונות של RIL unsolicited.

איור 4. תגובה לא רצויה של RIL.

הפתרון: קוד ה-Java שולח אישור לצד המקורי (ril.cpp) במקום להחזיק נעילת השכמה מתוזמנת בצד המקורי בזמן שליחת תגובה לא רצויה.

איור 5. השימוש ב-ack במקום ב-timed wakelock.

אימות של נעילות מעוררות שעוצבו מחדש

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