ל-AAOS יש ניהול נפח משלו ב-CarAudioService
. הוא משתמש בנפח קבוע, מתוך הנחה שצריך להחיל את הנפח מתחת ל-HAL באמצעות מגבר חומרה ולא בתוכנה. הוא גם מארגן את התקני הפלט לקבוצות נפח כדי להחיל את אותם הגברים על כל המכשירים המשויכים לקבוצת הנפח.
שימוש בנפח אחסון קבוע
בהטמעות של AAOS צריך לשלוט בעוצמת הקול באמצעות מגבר חומרה במקום באמצעות מיקסר תוכנה. כדי למנוע תופעות לוואי, מגדירים את הדגל config_useFixedVolume
כ-true (על גבי שכבת-על לפי הצורך):
<resources> <!-- Car uses hardware amplifier for volume. --> <bool name="config_useFixedVolume">true</bool> </resources>
כשהדגל config_useFixedVolume
לא מוגדר (או מוגדר כ-false), אפליקציות יכולות להפעיל את AudioManager.setStreamVolume()
ולשנות את עוצמת הקול לפי סוג הסטרימינג במיקסר התוכנה. יכול להיות שזה לא רצוי בגלל ההשפעה הפוטנציאלית על אפליקציות אחרות, והעובדה שהקטנת עוצמת הקול במיקסר התוכנה גורמת לכך שיהיו פחות ביטים משמעותיים שזמינים באות כשהוא מתקבל במגבר החומרה.
קבוצות של כרכים
קבוצות עוצמת קול מנהלות את עוצמת הקול של אוסף מכשירים בתחום אודיו. אפשר לשלוט בעוצמת הקול של כל קבוצת נפח בנפרד, והשיפורים שנובעים מכך מוגדרים במכשירים המשויכים כדי שהמגבר ברכב יוכל להחיל אותם. הגדרות עוצמת הקול נשמרות אצל המשתמש ונטענות כשהמשתמש נכנס לחשבון.
הגדרת קבוצות נפח אחסון
CarAudioService משתמש בקבוצות עוצמה שהוגדרו ב-car_audio_configuration.xml
:
<audioZoneConfiguration version="2.0"> <zones> <zone name="primary zone" isPrimary="true"> <volumeGroups> <group> <device address="bus0_media_out"> <context context="music"/> </device> </group> <group> <device address="bus1_navigation_out"> <context context="navigation"/> </device> <device address="bus2_voice_command_out"> <context context="voice_command"/> </device> </group> ... </volumeGroups> </zone> </zones> </audioZoneConfiguration>
דוגמה להטמעה של car_audio_configuration.xml
.
כל קבוצת נפח צריכה להכיל מכשיר פלט אחד או יותר עם כתובות משויכות.
הכתובות האלה צריכות להתאים למכשירי הפלט שמוגדרים ב-audio_policy_configuration.xml
.
הגדרת הגברה של קבוצת נפח
לכל קבוצת נפח יש ערכי רווח מינימלי, מקסימלי וברירת מחדל, וגם גודל שלב. הם נקבעים על סמך הערכים שמוגדרים ב-audio_policy_configuration.xml
למכשירים שמשויכים לקבוצת הנפח.
<devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS" address="bus0_media_out"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> <gains> <gain name="" mode="AUDIO_GAIN_MODE_JOINT" minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> </gains> </devicePort>
במהלך האינטליקציה, קבוצת הנפח תבדוק את ערכי ההגברה של המכשירים המשויכים ותגדיר את הקבוצה באופן הבא:
- גודל השלב חייב להיות זהה בכל המכשירים שבשליטת קבוצת האחסון
- רווח מינימלי ההגבלה המינימלית הקטנה ביותר מבין המכשירים בקבוצה
- רווח מקסימלי. השבח המקסימלי הגבוה ביותר מבין המכשירים בקבוצה
- רווח ברירת מחדל העלייה הגבוהה ביותר שמוגדרת כברירת מחדל מבין המכשירים בקבוצה
בגלל האופן שבו הערכים האלה מוגדרים, אפשר להגדיר את הרווח של קבוצת נפח מחוץ לטווח הנתמך למכשיר שמשויך לקבוצת הנפח. במקרה כזה, הגדרת הגבר למכשיר תהיה לפי הערך המינימלי או המקסימלי של הגבר במכשיר, בהתאם לכך שהערך של קבוצת עוצמת הקול נמוך או גבוה מהטווח.
מזהים של קבוצות נפח אחסון
קבוצות נפח מזוהות במהלך זמן הריצה לפי סדר ההגדרה שלהן בקובץ ה-XML.
המזהים נעים בין 0 ל-N-1 בתוך תחום אודיו, כאשר N הוא מספר קבוצות האחסון בתחום הזה. כך, מזהי קבוצות נפח אינם ייחודיים בין תחומים. המזהים האלה משמשים לממשקי API של CarAudioManager
שמשויכים לקבוצות נפח אחסון. כל ממשק API שמקבל groupId
ללא zoneId
יוגדר כברירת מחדל לאזור האודיו הראשי.
ניהול נפח אחסון בכמה תחומים
כל תחום אודיו אמור לכלול קבוצת נפח אחת או יותר, וכל קבוצת נפח משויכת רק לתחום אודיו אחד. הקשר הזה מוגדר כחלק מ-car_audio_configuration.xml
. אפשר לעיין בדוגמה שמופיעה בקטע הגדרת קבוצות נפח שלמעלה.
רמות עוצמת הקול הנוכחיות בכל תחום נשמרות למשתמש שמשויך לאותו תחום. ההגדרות האלה ספציפיות לאזור. כלומר, אם משתמש נכנס לחשבון במסך שמשויך לאזור הראשי, ולאחר מכן נכנס לאזור שמשויך לאזור אודיו משני, רמות עוצמת הקול שנטענו ונשמרו באזור הראשון יהיו שונות מאלה שנשמרו באזור השני.
טיפול באירועים של לחצני עוצמת הקול
ב-Android מוגדרים כמה קודי מפתחות לבקרת עוצמת הקול, כולל KEYCODE_VOLUME_UP
, KEYCODE_VOLUME_DOWN
ו-KEYCODE_VOLUME_MUTE
. כברירת מחדל, Android מפנה את האירועים של לחצן עוצמת הקול לאפליקציות. הטמעות לכלי רכב צריכות לאלץ את האירועים המרכזיים האלה ל-CarAudioService
, שיכול לקרוא ל-setGroupVolume
או ל-setMasterMute
בהתאם.
כדי לאלץ את ההתנהגות הזו, מגדירים את הדגל config_handleVolumeKeysInWindowManager
לערך true
:
<resources> <bool name="config_handleVolumeKeysInWindowManager">true</bool> </resources>
בשלב הזה אין דרך להבדיל בין אירועי מפתח של עוצמת קול לאזור שאליו הם מיועדים, ולכן ההנחה היא שכל האירועים האלה משויכים לאזור האודיו הראשי.
כשמתקבל אירוע של מקש עוצמת קול, CarAudioService
קובעת איזו קבוצת עוצמת קול לשנות על ידי אחזור הקשרי האודיו של הנגנים הפעילים, ולאחר מכן שינוי קבוצת עוצמת הקול שמכילה את מכשיר הפלט שמשויך להקשר האודיו עם העדיפות הגבוהה ביותר. תעדוף הבקשות נקבע על סמך סדר קבוע שמוגדר ב-CarVolume.AUDIO_CONTEXT_VOLUME_PRIORITY
.
הדרגה ואיזון
שתי הגרסאות של AudioControl HAL כוללות ממשקי API להגדרת עמעום ואיזון ברכב. יש ממשקי API תואמים למערכת עבור CarAudioManager, שמעבירים ערכים אל AudioControl HAL. ממשקי ה-API האלה דורשים את android.car.permission.CAR_CONTROL_AUDIO_VOLUME
.
ממשקי ה-API של AudioControl הם:
setBalanceTowardRight(float value)
. שינוי עוצמת הקול של הרמקולים בצד הימני (+) או בצד השמאלי (-) של הרכב. הערך 0.0 ממורכז, הערך +1.0 מימין לגמרי, הערך -1.0 מימין לגמרי וערך מחוץ לטווח -1 עד 1 הוא שגיאה.setFadeTowardFront(float value)
– שינוי עוצמת הקול של הרמקולים לחלק הקדמי (+) או האחורי (-) של הרכב. הערך 0.0 הוא מרכזי, הערך +1.0 הוא קדימה לגמרי, הערך -1.0 הוא אחורה לגמרי וערך מחוץ לטווח -1 עד 1 הוא שגיאה.
יצרני ציוד מקורי מחליטים איך להחיל את הערכים האלה ואיך הם יוצגו למשתמשים. אפשר להחיל אותם רק על מדיה או על כל הצלילים ב-Android.
ב-Android 11 נוספה גם תמיכה בהוספת אפקטים קוליים למכשירי פלט. כך אפשר לנהל את העמעום והאיזון באמצעות אפקטים של אודיו במכשירי הפלט המתאימים, במקום דרך ממשקי ה-API האלה.
הנמכה של עוצמת השמע
השתקה זמנית של אודיו מתרחשת כשהרכב מפחית את העוצמה של שידור אחד כדי ששידור אחר שמופעל בו-זמנית יהיה ברור יותר. ב-AAOS, ההטמעה של השקטת אודיו נתונה ל-HAL, כי יכול להיות שיש הרבה צלילים מחוץ ל-Android שאין למערכת ההפעלה שליטה עליהם. ב-Android 11, המידע העיקרי שזמין ל-HAL כדי לקבל החלטות לגבי השהיה הוא אם לשני מכשירי הפלט יש שני שידורים פעילים.
מתי כדאי להתכופף
ה-HAL של כל יצרן ציוד מקורי (OEM) קובע איך הוא יטפל בהשתקה, אבל יש כמה הנחיות כלליות שאנחנו ממליצים ליישם. בדרך כלל, מספר שידורים יפעלו ב-Android במקביל כששני אפליקציות או שירותים יתמקדו באודיו בו-זמנית. לכן, כדאי לעיין במאמר מטריצה של אינטראקציות כדי להבין מתי מערכת Android עשויה להעניק מיקוד בו-זמנית, וכתוצאה מכך מתי אפשר להפעיל שני שידורים שונים בו-זמנית.
חשוב לזכור שכל שילוב של שידורים ב-Android יתבצע לפני החלת הרווחים. לכן, כל שידור שצריך להקטין את עוצמת הקול שלו כשהוא מושמע בו-זמנית עם שידור אחר צריך להיות מנותב למכשירי פלט נפרדים, כדי ש-HAL יוכל להקטין את עוצמת הקול שלו לפני שהוא יתערבב עם השידור השני.
התנהגות מומלצת של השתקה
אלה אינטראקציות פוטנציאליות בו-זמניות שבהן מומלץ להשתמש בהשתקה:
EMERGENCY
. משמיקים או משתיקים את כל הערוצים חוץ מ-SAFETY
כדי לוודא שהנהג שומע את הצלילSAFETY
. משתקים את כל הצלילים חוץ מ-EMERGENCY
כדי לוודא שהנהג או הנהגת ישמעו את הצלילNAVIGATION
. Duck everything exceptSAFETY
andEMERGENCY
CALL
. עקף את כל האפשרויות חוץ מ-SAFETY
,EMERGENCY
ו-NAVIGATION
VOICE
. DuckCALL_RING
- יצרני ציוד מקורי צריכים לקבוע את מידת החשיבות של
VEHICLE_SOUNDS
הפעיל, ואם הם צריכים להנמיך צלילים אחרים כדי לוודא שהנהג ישמיע אותם. - כל הקוד צריך להימנע משימוש ב-
MUSIC
וב-ANNOUNCEMENT
. היוצא מן הכלל העיקרי הוא צלילים של אינטראקציה במגע, שמתנגנים כרגע בתורSYSTEM_SOUND
שיקולים נוספים כשמשתמשים בהשתקה
יכול להיות שבחלק מהאפליקציות או מהשירותים, כמו ניווט או Assistant, נעשה שימוש בכמה נגנים כדי להשלים את הפעולות שלהם. יצרני ציוד מקורי צריכים להימנע מביטול השתקה באופן אגרסיבי מדי על סמך הזמן שבו נתוני הסטרימינג מפסיקים להגיע דרך יציאות האות האלה, כדי לוודא שהמדיה לא תשוב לרגע לעוצמת קול מלאה לפני שהיא תושתק שוב כשהפעלת ההשמעה הבאה תתחיל באפליקציית הניווט או באפליקציית העוזרת.
בכלי רכב עם כמה מיקומי מיקרופון עם בידוד טוב מספיק, יש גם אפשרות לנתב את האודיו לאזורים שונים ברכב במקום להשתמש בהשתקה. לדוגמה, אפשר להעביר הוראות ניווט לרמקול של משענת הראש של הנהג, בזמן שהמוזיקה ממשיכה להתנגן בכל רחבי תא הנוסעים בעוצמה רגילה.
צלילים קריטיים לבטיחות
ב-Android 11 הושקעו ממשקי API של HAL ל-audio focus, אבל עדיין ה-HAL אחראי לוודא שצלילים קריטיים לבטיחות מקבלים עדיפות על פני צלילים אחרים. גם אם ה-HAL מחזיק את המיקוד של האודיו עבור USAGE_EMERGENCY
, זה לא מבטיח שאפליקציות ושירותים ב-Android לא ישמיעו צלילים. ה-HAL הוא זה שקובע אילו שידורים מ-Android יש לערבב או להשתיק כשמתנגנים צלילים קריטיים לבטיחות.
הגדרת ממשק המשתמש של הגדרות עוצמת הקול
מערכת AAOS מפרידה בין ממשק המשתמש של הגדרות עוצמת הקול לבין הגדרת קבוצות נפח (שאפשר להציג מעליהם שכבת-על כפי שמתואר בקטע 'הגדרת קבוצות נפח'). ההפרדה הזו מבטיחה שלא נדרשים שינויים אם ההגדרות של קבוצות האחסון ישתנו בעתיד.
בממשק המשתמש של הגדרות הרכב, הקובץ packages/apps/Car/Settings/res/xml/car_volume_items.xml
מכיל רכיבי ממשק משתמש (משאבי שם וסמל) שמשויכים לכל AudioAttributes.USAGE
שהוגדר. הקובץ הזה מספק עיבוד סביר של VolumeGroups
המוגדר באמצעות משאבים שמשויכים לשימוש הראשון שזוהה בכל VolumeGroup.
לדוגמה, בדוגמה הבאה מוגדרת קבוצת נפח (VolumeGroup) שכוללת גם את voice_communication
וגם את voice_communication_signalling
. בהטמעה שמוגדרת כברירת מחדל של ממשק המשתמש של הגדרות הרכב, המערכת מייצרת את VolumeGroup באמצעות המשאבים המשויכים ל-voice_communication
כי זהו המשאב הראשון בקובץ.
<carVolumeItems xmlns:car="http://schemas.android.com/apk/res-auto"> <item car:usage="voice_communication" car:title="@*android:string/volume_call" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="voice_communication_signalling" car:title="@*android:string/volume_call" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="media" car:title="@*android:string/volume_music" car:icon="@*android:drawable/ic_audio_media"/> <item car:usage="game" car:title="@*android:string/volume_music" car:icon="@*android:drawable/ic_audio_media"/> <item car:usage="alarm" car:title="@*android:string/volume_alarm" car:icon="@*android:drawable/ic_audio_alarm"/> <item car:usage="assistance_navigation_guidance" car:title="@string/navi_volume_title" car:icon="@drawable/ic_audio_navi"/> <item car:usage="notification_ringtone" car:title="@*android:string/volume_ringtone" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="assistant" car:title="@*android:string/volume_unknown" car:icon="@*android:drawable/ic_audio_vol"/> <item car:usage="notification" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_communication_request" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_communication_instant" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_communication_delayed" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_event" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="assistance_accessibility" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="assistance_sonification" car:title="@*android:string/volume_unknown" car:icon="@*android:drawable/ic_audio_vol"/> <item car:usage="unknown" car:title="@*android:string/volume_unknown" car:icon="@*android:drawable/ic_audio_vol"/> </carVolumeItems>
המאפיינים והערכים שמשמשים בתצורה שלמעלה מפורטים ב-packages/apps/Car/Settings/res/values/attrs.xml
. ממשק המשתמש של הגדרות עוצמת הקול משתמש בממשקי ה-API הבאים של CarAudioManager שמבוססים על VolumeGroup:
getVolumeGroupCount()
כדי לדעת כמה אמצעי בקרה צריך לצייר.getGroupMinVolume()
ו-getGroupMaxVolume()
כדי לקבל גבולות תחתון וגבוה.getGroupVolume()
כדי לקבל את עוצמת הקול הנוכחית.registerVolumeChangeObserver()
כדי לקבל התראות על שינויים בעוצמה.