אודיו לכלי רכב

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

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

ב-Android 11 בוצעו השינויים הבאים באודיו שקשור לכלי רכב :

צלילים וסטרימינג ב-Android

מערכות אודיו בכלי רכב מטפלות בצלילים ובשידורים הבאים:

תרשים ארכיטקטורה ממוקד-זרם

איור 1. תרשים ארכיטקטורה ממוקד-זרם

מערכת Android מנהלת את הצלילים שמגיעים מאפליקציות ל-Android ושולטת באפליקציות האלה וניתוב הצלילים שלהם למכשירי פלט ב-HAL בהתאם לסוג Sound:

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

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

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

צלילים של Android

באפליקציות יכולות להיות שחקן אחד או יותר שיוצרים אינטראקציה דרך מכשיר Android הרגיל ממשקי API (לדוגמה, AudioManager). לפקדים להתמקדות או ל-MediaPlayer לסטרימינג) כדי לשדר סטרימינג לוגי אחד או יותר של נתוני אודיו. הנתונים האלה יכול להיות מונו של ערוץ יחיד או סראונד 7.1, אבל הוא מנותב ומטופל כמו במקור יחיד. שידור האפליקציה משויך ל-AudioAttributes שמספקים למערכת טיפים לגבי האופן שבו האודיו צריך לבטא.

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

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

שידורים חיצוניים

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

אם שידורים חיצוניים הם מקורות מדיה שצריכים לקיים אינטראקציה עם הצליל מערכת Android מייצרת (לדוגמה, להפסיק את הפעלת ה-MP3 כאשר הטיונר החיצוני מופעל), השידורים החיצוניים האלה צריכים להיות מיוצגים על ידי אפליקציה ל-Android. אפליקציה כזו תבקש התמקדות באודיו בשם מקור המדיה במקום ב-HAL, והוא יגיב להתראות ממוקדות באמצעות הפעלה/עצירה של המקור החיצוני לפי הצורך כדי להתאים את המיקוד ל-Android המדיניות בנושא האפליקציה אחראית גם לטיפול באירועים מרכזיים במדיה כמו הפעלה והשהיה. אחד מהמנגנונים המוצעים לשליטה במכשירים חיצוניים כאלה הוא HwAudioSource.

מכשירי פלט

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

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

ההקצאה של הקשרי אודיו למכשירי פלט מתבצעת באמצעות car_audio_configuration.xml

קלט המיקרופון

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

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

קלט מיקרופון מרובה-ערוצים

כדי להקליט אודיו ממכשיר שבו יש יותר משני ערוצים (סטריאו), השתמש מסכת אינדקס ערוצים במקום מסכת אינדקס תלוי מיקום (כמו CHANNEL_IN_LEFT). דוגמה:

final AudioFormat audioFormat = new AudioFormat.Builder()
    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    .setSampleRate(44100)
    .setChannelIndexMask(0xf /* 4 channels, 0..3 */)
    .build();
final AudioRecord audioRecord = new AudioRecord.Builder()
    .setAudioFormat(audioFormat)
    .build();
audioRecord.setPreferredDevice(someAudioDeviceInfo);

כשגם setChannelMask וגם setChannelIndexMask מוגדרות, AudioRecord משתמש רק בערך שהוגדר על ידי setChannelMask (עד שני ערוצים).

צילום בו-זמנית

החל מ-Android 10, ה-framework של Android תומך בצילום בו-זמנית של קלט, אך עם הגבלות כדי להגן על פרטיות המשתמש. כחלק של ההגבלות האלה, מקורות וירטואליים כמו מתעלמים מ-AUDIO_SOURCE_FM_TUNER, ולכן מותר להם שהוקלט בו-זמנית עם קלט רגיל (כמו המיקרופון). כמו כן, HwAudioSources לא נחשבים כחלק ממופעים בו-זמנית את ההגבלות על תיעוד.

אפליקציות שנועדו לפעול עם מכשירי AUDIO_DEVICE_IN_BUS או עם מכשירי AUDIO_DEVICE_IN_FM_TUNER משניים חייבים להסתמך על זיהוי המכשירים האלה ושימוש ב-AudioRecord.setPreferredDevice() כדי לעקוף את לוגיקת ברירת המחדל של בחירת המקור ב-Android.

שימושים באודיו

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

שימושים של המערכת

ב-Android 11 הוספנו את השימושים במערכת. השימושים האלה מתנהגים בדומה לשימושים הקודמים, אלא אם הם דורשים ממשקי API של המערכת לשימוש וגם android.permission.MODIFY_AUDIO_ROUTING. הגרסה החדשה השימושים במערכת הם:

  • USAGE_EMERGENCY
  • USAGE_SAFETY
  • USAGE_VEHICLE_STATUS
  • USAGE_ANNOUNCEMENT

כדי ליצור AudioAttributes עם שימוש במערכת, צריך להשתמש AudioAttributes.Builder#setSystemUsage במקום setUsage. קריאה לשיטה הזו עם שימוש שאינו במערכת יובילו להשלכה של IllegalArgumentException. כמו כן, אם גם השימוש במערכת וגם השימוש הוגדרו ב-builder, IllegalArgumentException בזמן הבנייה.

כדי לבדוק איזה שימוש משויך אל AudioAttributes קוראים לפונקציה AudioAttributes#getSystemUsage. הפעולה הזו מחזירה את השימוש או את השימוש במערכת המשויכים.

הקשרי אודיו

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

הקשרי האודיו ב-Android 11 הם:

הקשר אודיו AttributeUsages (שימושים משויכים)
MUSIC UNKNOWN, GAME, MEDIA
NAVIGATION ASSISTANCE_NAVIGATION_GUIDANCE
VOICE_COMMAND ASSISTANT, ASSISTANCE_ACCESSIBILITY
CALL_RING NOTIFICATION_RINGTONE
CALL VOICE_COMMUNICATION, VOICE_COMMUNICATION_SIGNALING
ALARM ALARM
NOTIFICATION NOTIFICATION, NOTIFICATION_*
SYSTEM_SOUND ASSISTANCE_SONIFICATION
EMERGENCY EMERGENCY
SAFETY SAFETY
VEHICLE_STATUS VEHICLE_STATUS
ANNOUNCEMENT ANNOUNCEMENT

מיפוי בין הקשרי אודיו ושימושים. השורות המודגשות הן עבור הודעות חדשות שימושי המערכת.

אודיו במספר אזורים

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

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

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

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

הגדרת אודיו בכמה אזורים

איור 2. הגדרת אודיו במספר אזורים

אודיו HAL

בהטמעות אודיו בכלי רכב נעשה שימוש בתקן Android Audio HAL. שכולל את הפרטים הבאים:

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

סוגי מכשירים בכלי רכב

סוגי המכשירים הבאים רלוונטיים לפלטפורמות של כלי רכב.

סוג מכשיר תיאור
AUDIO_DEVICE_OUT_BUS פלט ראשי מ-Android (כך כל האודיו מ-Android נמסרה לרכב). משמשת ככתובת להבחנה בין שידורים חיים לכל הקשר.
AUDIO_DEVICE_OUT_TELEPHONY_TX משמש לאודיו שמנותב לרדיו הסלולרי לצורך שידור.
AUDIO_DEVICE_IN_BUS משמש לקלטים שלא סווגו באופן אחר.
AUDIO_DEVICE_IN_FM_TUNER משמש רק לשידור של קלט רדיו.
AUDIO_DEVICE_IN_TV_TUNER משמש למכשיר טלוויזיה, אם יש כזה.
AUDIO_DEVICE_IN_LINE משמש לשקע קלט AUX.
AUDIO_DEVICE_IN_BLUETOOTH_A2DP מוזיקה התקבלה באמצעות Bluetooth.
AUDIO_DEVICE_IN_TELEPHONY_RX משמש לאודיו שהתקבל מהרדיו הסלולרי המשויך לטלפון שיחה.

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

צריך להגדיר התקני אודיו שגלויים ל-Android לפי /audio_policy_configuration.xml, שכולל את הרכיבים הבאים:

  • שם המודול. תומך בערך 'ראשי' (משמש בתרחישים לדוגמה של כלי רכב), 'A2DP', 'remote_submix' ו-'USB'. שם המודול והאודיו התואם צריך לבצע הידור של מנהל ההתקן ל-audio.primary.$(variant).so.
  • יציאות מכשיר. מכילה רשימה של תיאורי מכשירים לכל הקלט והפלט מכשירים (כולל מכשירים שמחוברים באופן קבוע והתקנים נשלפים) שניתן בוצעה גישה מהמודול הזה.
    • לכל מכשיר פלט אפשר להגדיר השגת שליטה שכוללת ערכי min/max/default/step במיליבל (1 מיליבל = 1/100 dB = 1/1000 bel).
    • אפשר להשתמש במאפיין address במכונת devicePort כדי למצוא גם אם יש כמה מכשירים עם אותו סוג מכשיר כמו AUDIO_DEVICE_OUT_BUS
  • ערבוב יציאות. מכילה רשימה של כל זרמי הפלט והקלט שנחשפים על ידי אודיו HAL. אפשר להחשיב כל מופע של microPort כסטרימינג פיזי כדי שירות Android AudioService.
  • למסלולים. מגדיר רשימה של חיבורים אפשריים בין קלט לפלט בין מכשירים או משדרים בסטרימינג לבין מכשירים אחרים.

הדוגמה הבאה מגדירה ערך bus0_phone_out של מכשיר פלט שבו כל שידורי האודיו ב-Android משולבים על ידי Mixer_bus0_phone_out. המסלול לוקח את פלט זרם של mixer_bus0_phone_out למכשיר bus0_phone_out.

<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>bus0_phone_out</item>
<defaultOutputDevice>bus0_phone_out</defaultOutputDevice>
            <mixPorts>
                <mixPort name="mixport_bus0_phone_out"
                         role="source"
                         flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="bus0_phone_out"
                            role="sink"
                            type="AUDIO_DEVICE_OUT_BUS"
                            address="BUS00_PHONE">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                    <gains>
                        <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                minValueMB="-8400"
                                maxValueMB="4000"
                                defaultValueMB="0"
                                stepValueMB="100"/>
                    </gains>
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="bus0_phone_out"
                       sources="mixport_bus0_phone_out"/>
            </routes>
        </module>
    </modules>
</audioPolicyConfiguration>