שירות פלאגין של אודיו לרכב

שירותי פלאגין חדשים של יצרני ציוד מקורי לכלי רכב ב-Android 14 מאפשרים להגדיר חלק מרכיבי הרכב. במיוחד לגבי אודיו, הוספנו שלושה שירותי פלאגין חדשים שמאפשרים ליצרני ציוד מקורי להגדיר באופן גמיש את ניהול האודיו במכשירי AAOS:

  • שליטה במיקוד האודיו
  • שליטה בעוצמת הקול ובהשתקה של האודיו
  • שליטה בהנמכה של עוצמת השמע

הארכיטקטורה של שירות הפלאגין לרכב

בתרשים הבא מוצגת סקירה כללית של שירותי הרכב והקשר שלהם לשירות הרכב של יצרן ציוד מקורי (OEM). בדומה לתהליכי האפליקציות ולתהליך שירות הרכב, תהליך שירות הרכב של יצרן ציוד מקורי תופס נפח משלו.

תמונה

שירות הרכב מפעיל את שירות הרכב של יצרן הציוד המקורי על ידי חיפוש הרכיב שמוגדר ב-config_oemCarService. אם הקובץ ריק, שירות ה-OEM לא קיים ואף שירות לא מופעל. הרכיב חייב להרחיב את OemCarService. שירות האודיו ברכב צריך לשכתב את ממשקי ה-API לקבלת שירות האודיו של יצרן ציוד מקורי לרכב:

public final class OemCarServiceImp extends OemCarService {
    @Override
    public OemCarAudioFocusService getOemAudioFocusService();

    @Override
    public OemCarAudioDuckingService getOemAudioDuckingService();

    @Override
    public OemCarAudioVolumeService getOemAudioVolumeService();
}

לדוגמה, ראו את אפליקציית הבדיקה לדוגמה שמוגדרת בקובץ packages/services/Car/tests/OemCarServiceTestApp.

אף על פי שהשירות מופעל על ידי שירות הרכב, הוא לא יורש באופן אוטומטי את ההרשאות הזמינות לשירות האודיו ברכב. לכן, כל הרשאה שנדרשת לשירותי OEM צריכה להתקבל באמצעות המנגנון המתאים. לדוגמה, packages/services/Car/data/etc/com.android.car.oemcarservice.testapp.xml.

שירות אודיו לרכב עם ארכיטקטורת שירות של יצרן ציוד מקורי (OEM)

ב-AAOS, שירות האודיו ברכב מנהל את הפעולות הבאות:

  • ניתוב אודיו
  • מיקוד אודיו
  • הנמכה של עוצמת השמע
  • עוצמת הקול והשתקה

לפני Android 14, ההתנהגות הזו הייתה סטטית במידה רבה, וניתן היה לשנות אותה רק דרך ההגדרות, אבל רק בקבוצה מוגבלת מאוד של מקרים. ב-Android 14 הושק מנגנון לשירות האודיו ברכב, שמאפשר תקשורת עם רכיב שהוגדר על ידי יצרן ציוד מקורי (OEM) ומנהל את הדברים הבאים:

  • מיקוד אודיו
  • הנמכה של עוצמת השמע
  • עוצמת הקול והשתקה

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

תמונה

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

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

כדי לבצע פעולות, שירות האודיו ברכב קורא לשירותי הרכב של יצרן ציוד מקורי (OEM). הקריאות האלה מתבצעות בין תהליכים, ולכן נדרש תקשורת בין תהליכים (IPC). IPC מוסיף זמן אחזור לכל קריאה. חשוב לצמצם את זמן האחזור בשירות של יצרן הציוד המקורי.

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

הגדרות של שירותי אודיו לרכב של יצרני ציוד מקורי

שירות להרשאת אודיו ברכב של יצרן ציוד מקורי

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

  • אינטראקציה בו-זמנית בעלי הרשאת ה'מיקוד' יכולים לשמור על המיקוד בו-זמנית.

  • אינטראקציות בלעדיות. בקשת מיקוד נכנסת תוביל להעברת המיקוד מהמשתמש הנוכחי שמחזיק בו.

  • לדחות את האינטראקציה. בקשת מיקוד נכנסת נדחתה על סמך בעל המיקוד הנוכחי.

האפשרות הזו מספיקה לחלק מתרחישי השימוש בתחום הרכב, אבל היא לא עומדת בכל הצרכים של האינטראקציה, שעשויים להיות שונים עקב דרישות של יצרני ציוד מקורי (OEM). לשם כך, אנחנו משיקים את OemCarAudioFocusService:

public interface OEmCarAudioFocusService {
    OemCarAuddioFocusResults evaluateAudioFocusRequest(
        OemCarAudioFocusEvaluationRequest request);
    
    void notifyAudioFocusChange(
        List<AudioFocusEntry> holder,
        List<AudioFocusEntry> losers, int zoneId);
}

ה-API evaluateAudioFocusRequest נקרא משירות האודיו ברכב בכל פעם שיש בקשה להתמקד באודיו שצריך להעריך. זהו API דו-כיווני שחוסם עד שהתוצאות יחזרו. הבקשה מכילה מידע על המצב הנוכחי של סטאק האודיו:

אפשר להשתמש במידע הזה כדי להעריך את newFocusRequest בהשוואה לבעלים הנוכחיים של מוקד העניין ב-focusHolders ולבעלי מוקד העניין הנוכחיים שמאבדים אותו ב-focusLosers. ה-API אמור להחזיר את התוצאות הבאות:

class OemCarAudioFocusResult {
    int audioZoneId;
    int audioFocusEvaluationResults;
    AudioFocusEntry focusResult;
    List<AudioFocusEntry> newLosers;
    List<AudioFocusEntry> newlyBlocked;
}

השדה הזה מכיל את המידע על תוצאות הבדיקה בפועל ב-audioFocusEvaluationResults, שמציין אם הבקשה הנוכחית אושרה, הושהתה או נכשלה. כל שינוי ב-stack הנוכחי של המיקוד צריך להגדיר ברשומה newLosers וברשומה newlyBlocked, בהתאם לאופי השינוי ב-stack.

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

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

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

הנחיות להערכת המיקוד

ב-AAOS, התכונה 'מיקוד אודיו' משמשת לניהול ההפעלה של האודיו ולקביעת האפליקציה שצריכה להתמקד בו כדי לספק למשתמש חוויה אופטימלית. לכן, כשמנהלים בקשה להתמקד באודיו, שירות הפלאגין של ה-OEM צריך להביא בחשבון את הגורמים הבאים:

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

  • כשהתכונת 'מיקוד במדיה' פעילה, אפליקציות שמבקשות:

    • צריך להיות אפשרות להתמקד בשימוש בשיחה בו-זמנית או באופן בלעדי.

    • התמקדות ברכיב ממשק לניווט, צריכה להיות אפשרית בו-זמנית או באופן בלעדי.

    • הרכיב של Assistant שמשמש אתכם צריך לקבל את המיקוד בו-זמנית או באופן בלעדי.

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

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

שירות עוצמת קול ברכב של יצרן ציוד מקורי

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

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

  1. ניווט
  2. התקשרות
  3. מוזיקה
  4. הכרזה
  5. פקודה קולית
  6. צלצול שיחה
  7. צלילי מערכת
  8. בטיחות
  9. התראה
  10. התראה
  11. סטטוס הרכב
  12. חירום

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

  1. התקשרות
  2. מדיה
  3. הכרזה
  4. פקודה קולית

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

אפשר להגדיר את הגרסה בפועל של האוסף באמצעות ההגדרה audioVolumeAdjustmentContextsVersion. אפשר להגדיר את התצורה ל-1 או ל-2 (2 הוא ברירת המחדל).

כדי לספק גמישות רבה יותר בניהול עוצמת הקול, הוספנו את OemCarAudioVolumeService ב-Android 14:

public interface OemCarAudioVolumeService {
    OemCarvolumeChangeInfo getSuggestedGroupForVolumeChange(
OemCarAudioVolumeRequest request, int volumeAdjustment);
}

לשירות עוצמת האודיו ברכב של יצרן ציוד מקורי יש שיטה אחת, שמקבלת volumeAdjustment ו-OemCarAudioVolumeRequest:

class OemCarAudioVolumeRequest {
    int audioZoneId;
    int callState;
    List<AudioAttributes> activePlaybackAttributes;
    List<AudioAttributes> duckedAttributes;
    List<CarVolumeGroupInfo> volumeGroupState;
}

השדה activePlaybackAttributes של הבקשה מכיל את מאפייני האודיו הפעילים. הערכים של duckedAttributes הם כל מאפייני האודיו שמושתקים כרגע. השדה volumeGroupState מכיל את המצב הנוכחי של קבוצת האחסון. הבקשה מייצגת את המצב הנוכחי של סטאק האודיו, וניתן להשתמש בה כדי לקבוע איזו קבוצת עוצמת קול צריך לשנות. התוצאות צריכות להופיע ב-OemCarVolumeChangeInfo:

class OemCarVolumeChangeInfo {
    boolean change;
    CarVolumeGroupInfo volumeGroupChanged;
}

הערך הבוליאני change מציין אם נפח כלשהו השתנה, הערך true מציין שיש שינוי וצריך לעדכן את קבוצת הנפחים. הערך volumeGroupChanged הוא קבוצת האחסון בפועל שצריך לשנות. צריך לשנות את הקבוצה הזו בהתאם למשתנה volumeAdjustment המקורי שהוענק ל-API. לדוגמה, אם התוצאות מצביעות על כך שקבוצת עוצמת הקול של הניווט צריכה להיות מושתקת, הערך הבוליאני יהיה true וקבוצת עוצמת הקול שתוחזר צריכה להיות זו של הניווט.

שירות הנמכה אוטומטית של עוצמת הקול ברכב של יצרן ציוד מקורי

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

  • צלילים במקרה חירום משתקים את כל הצלילים חוץ מצלילים של שיחות
  • התכונה 'בטיחות' משתיקה את כל הצלילים מלבד צלילים במקרה חירום
  • הניווט משמייט את כל הצלילים חוץ מהצלילים של התראות הבטיחות וההתראות המצב החירום
  • כשאתם מדברים, המערכת משתיקה את כל הצלילים חוץ מהצלילים של התכונות הבטיחותיות, צלילי החירום וצלילי הניווט
  • צלצולים של שיחות קוליות עם ברווזים
  • המוזיקה וההכרזות צריכות להיות מושתקות על ידי כל הצלילים האחרים

הכללים האלה לא מקיפים, ו-OEMs אחראים לקבוע איך להפחית את עוצמת הקול של הצלילים על סמך ההנחיות האלה. יצרני ציוד מקורי יכולים לשלוט בהמלצות האלה באופן פעיל יותר על סמך הדרישות הזמינות. השדה OemCarDuckingService מופיע ב-Android 14:

class OemCarAudioDuckingService {
List<AudioAttributes>   evaluateAttributesToDuck(
        OemCarAudioVolumeRequest request);
}

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

  • מאפיין האודיו שמושהה כרגע:

    • ברשימה, ממשיכים להסתיר אותו
    • לא ברשימה, ההשתקה מושבתת
  • מאפיין האודיו לא מושתק כרגע:

    • ברשימה, מושבת
    • לא ברשימה, ההשתקה מושבתת

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

באיור הבא מוצג תרשים רצף פשוט של בקרת ההשתקה של האודיו לבקשת התמקדות כשמשתמשים בשירות ההשתקה של OEM:

תמונה

התהליך מתחיל כשאפליקציה מבקשת לנהל את המיקוד באודיו דרך ממשקי API ציבוריים לניהול אודיו. הבקשה מועברת לשירות האודיו ברכב כדי לקבוע את התוצאות. כשמתקבלת החלטה לגבי מוקד האודיו, שירות האודיו ברכב מבצע הערכה של ההשתקה של האודיו באמצעות קריאה ל-OemCarAudioDuckingService כדי להעריך אילו מאפייני אודיו צריך להשתיק. אחרי שהתוצאות מחזירות את ה-API של evaluateAttributesToDuck, מחשבים את מכשירי האודיו שצריך להפחית את עוצמת הקול שלהם, ובסוף המידע נשלח אל AudioControl כדי להחיל את ההפחתה על חומרת האודיו.

הטמעת הפניה לשירות אודיו ברכב של יצרן ציוד מקורי (OEM)

מערכת AAOS מספקת הטמעת עזר של שירות הרכב של יצרן הציוד המקורי ב-packages/services/Car/tests/OemCarServiceTestApp, שמטמיעה את OemCarService, יחד עם OemCarAudioFocusService,‏ OemCarAudioDuckingService ו-OemCarAudioVolumeService. במקרה השני, כל שירות משתמש בקובץ XML כדי לטעון התנהגות סטטית. לדוגמה, הפונקציה OemCarAudioFocusServiceImp טוענת את oem_focus_config.xml, שמכיל מטריצת אינטראקציה. המטריצה משמשת להערכת בקשת המיקוד כשמתבצעת קריאה ל-evaluateAudioFocusRequest.

ניפוי באגים באפליקציית בדיקה לדוגמה

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

<!-- This is the component name for the OEM customization service. OEM can choose to implement
this service to customize car service behavior for different policies. If OEMs choose to
implement it, they have to implement a service extending OemCarService exposed by car-lib,
and implement the required component services.
If the component name is invalid, CarService would not connect to any OEM service.
Component name can not be a third party package. It should be pre-installed -->
<string name="config_oemCarService" translatable="false">
com.android.car.oemcarservice.testapp/.OemCarServiceImpl
</string>

כדי לוודא ששירות הרכב של יצרן ציוד מקורי משתמש בפקודה dump של שירות הרכב עבור שירות יצרן הציוד המקורי:

adb shell dumpsys car_service --oem-service

התוצאות עשויות להיראות כך:

***CarOemProxyService dump***
  mIsFeatureEnabled: true
  mIsOemServiceBound: true
  mIsOemServiceReady: true
  mIsOemServiceConnected: true
  mInitComplete: true
  OEM_CAR_SERVICE_CONNECTED_TIMEOUT_MS: 5000
  OEM_CAR_SERVICE_READY_TIMEOUT_MS: 5000
  mComponentName: com.android.car.oemcarservice.testapp/.OemCarServiceImpl

כל ערך בוליאני בכל קבוצה של פרטי dump קובע את המצב של התכונה והשירות. לדוגמה, המידע ב-dump mIsOemServiceReady מציין אם השירות מוכן לשימוש, כאשר הערך true מציין שהוא מוכן והערך false מציין שהוא לא מוכן.