ניתוב אודיו

ב-Android 10, car_audio_configuration.xml מחליף את car_volumes_groups.xml ואת IAudioControl.getBusForContext. קובץ התצורה החדש מגדיר רשימה של תחומים. לכל תחום יש לפחות קבוצת נפח אחת עם המכשירים המשויכים אליה, וכל מכשיר מכיל את ההקשרים שצריך לנתב באותו תחום. חובה לייצג את כל ההקשרים בכל תחום.

הגדרת ניתוב האודיו

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

הפעלת ניתוב ב-AAOS

כדי להשתמש בחיבור מבוסס-AAOS, צריך להגדיר את הדגל audioUseDynamicRouting לערך true:

<resources>
    <bool name="audioUseDynamicRouting">true</bool>
</resources>

כשהאפשרות false תושבת, הניתוב וחלק גדול מ-CarAudioService יושבתו, והמערכת תעבור לברירת המחדל של AudioService.

תחום ראשי

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

הגדרה לדוגמה

לדוגמה, ברכב יכולים להיות שני אזורים – אזור ראשי ומערכת בידור במושב האחורי. כך אפשר להגדיר car_audio_configuration.xml אפשרי:

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true">
           <volumeGroups>
               <group>
                   <device address="bus0_media_out">
                       <context context="music"/>
                       <context context="announcement"/>
                   </device>
                   <device address="bus3_call_ring_out">
                       <context context="call_ring"/>
                   </device>
                   <device address="bus6_notification_out">
                       <context context="notification"/>
                   </device>
                   <device address="bus7_system_sound_out">
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                   </device>
               </group>
               <group>
                   <device address="bus1_navigation_out">
                       <context context="navigation"/>
                   </device>
                   <device address="bus2_voice_command_out">
                       <context context="voice_command"/>
                   </device>
               </group>
               <group>
                   <device address="bus4_call_out">
                       <context context="call"/>
                   </device>
               </group>
               <group>
                   <device address="bus5_alarm_out">
                       <context context="alarm"/>
                   </device>
               </group>
           </volumeGroups>
       </zone>
        <zone name="rear seat zone" audioZoneId="1">
           <volumeGroups>
               <group>
                   <device address="bus100_rear_seat">
                       <context context="music"/>
                       <context context="navigation"/>
                       <context context="voice_command"/>
                       <context context="call_ring"/>
                       <context context="call"/>
                       <context context="alarm"/>
                       <context context="notification"/>
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                       <context context="announcement"/>
                   </device>
               </group>
           </volumeGroups>
    </zones>
</audioZoneConfiguration>

כאן, ההקשרים הופרדו במרחב הראשי למכשירים שונים. כך ה-HAL יכול להחיל אפקטים שונים של עיבוד נתונים לאחר העיבוד (post-processing) ומילוי (mixing) בכל פלט של המכשיר באמצעות החומרה של הרכב. המכשירים מחולקים לארבע קבוצות של עוצמת קול: מדיה, ניווט, שיחות והתראות. אם המערכת מוגדרת ל-useFixedVolume, רמות עוצמת הקול של כל קבוצה יועברו ל-HAL כדי להחיל אותן על הפלט של המכשירים האלה.

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

הגדרת האודיו של אזור הנוסעים

ב-Android 11, השדה car_audio_configuration.xml הורחב ונוספו לו שני שדות חדשים, audioZoneId ו-occupantZoneId. אפשר להשתמש בשדה הראשון, audioZoneId, כדי לשלוט טוב יותר בניהול האזורים. לעומת זאת, אפשר להשתמש ב-occupantZoneId כדי להגדיר ניתוב שמבוסס על מזהה משתמש.

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

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true" occupantZoneId="0">
         ...
       </zone>
       <zone name="rear seat zone" audioZoneId="1" occupantZoneId="1">
         ...
       </zone>
    </zones>
</audioZoneConfiguration>

ההגדרה שלמעלה מגדירה מיפוי של האזור הראשי לאזור הדייר 0, ושל audioZoneId 1 ל-occupantZoneId 1. באופן כללי, אפשר להגדיר כל מיפוי בין תחום הנוסעים לבין תחום האודיו, אבל המיפוי חייב להיות אחד לאחד. אלה הכללים שהגדירו את שני השדות החדשים:

  • הערך של audioZoneId עבור האזור הראשי הוא תמיד אפס
  • אי אפשר לחזור על המספרים audioZoneId ו-occupantZoneId
  • אפשר ליצור רק מיפוי אחד-לאחד בין audioZoneId לבין occupantZoneId

ניתוב דרך מזהה ייחודי (UID) של אפליקציה

סדרה של ממשקי API מוסתרים נוספו ל-CarAudioManager בגרסה 10 כדי לאפשר לאפליקציות לשלוח שאילתות ולהגדיר אזורי אודיו ומיקוד.

int[] getAudioZoneIds();
int getZoneIdForUid(int uid);
boolean setZoneIdForUid(int zoneId, int uid);
boolean clearZoneIdForUid(int uid);

ממשקי ה-API שלמעלה אפשרו לאפליקציה של צד ראשון לנהל את ניתוב האודיו על סמך מזהה ה-UID של האפליקציה. לכן, נדרשים גם מזהה תחום האודיו וגם ה-UID של האפליקציה. לאחר מכן אפשר להגדיר את ניתוב האודיו באמצעות API ‏CarAudioManager#setZoneIdForUid.

שינוי תחומים לאפליקציה

כברירת מחדל, כל האודיו מנותב לאזור הראשי. כדי לעדכן אפליקציה כך שהיא תנותב לאזור אחר, משתמשים ב-CarAudioManager#setZoneIdForUid:

// Find zone to play
int zoneId = ...

// Find application's uid
Int uid = mContext.getPackageManager()
        .getApplicationInfo(mContext.getPackageName(), 0)
        .uid;

if (mCarAudioManager.setZoneIdForUid(zoneId, info.uid)) {
    Log.d(TAG, "Zone successfully updated");
} else {
    Log.d(TAG, "Failed to change zone");
}

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

ניתוב באמצעות User‑ID

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

עדיין אפשר להשתמש בחיבור מבוסס-UID של אפליקציות, אבל צריך לעשות זאת בנפרד מחיבור מבוסס-User-ID. המשמעות היא שאם מגדירים מיפוי של אזור הנוסעים לאזור האודיו ברכב, הניתוב שמבוסס על UID מושבת, וניסיון לקרוא ל-CarAudioManager#setZoneidForUid יגרום להצגת שגיאה.

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

ניתוב באמצעות setPreferredDevice

בנוסף לשינויים שלמעלה, ב-Android 11 יש גם ממשק API חדש לשליחת שאילתות למכשירי הפלט המשויכים לכל תחום, ‏CarAudioManager#getOutputDeviceForUsage(int zoneId, int usage).

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

audioZoneId = ... ;
mediaDeviceInfo = mCarAudioManager
            .getOutputDeviceForUsage(audioZoneId, AudioAttributes.USAGE_MEDIA);
…
mPlayer.setPreferredDevice(mediaDeviceInfo);