音量管理

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 檔案中的定義順序進行標識。音訊區域內的 ID 範圍為 0 到 N-1,其中 N 是該區域中捲組的數量。這樣,磁碟區組 ID 在區域之間就不是唯一的。這些標識符用於與磁碟區組關聯的CarAudioManager API。任何接受groupId而沒有zoneId API 將預設為主音訊區域。

多區域捲管理

每個音訊區域應具有一個或多個卷組,並且每個卷組僅與單一音訊區域相關聯。此關係定義為car_audio_configuration.xml的一部分。請參閱上面定義卷組中提供的範例。

每個區域的當前音量等級對於與該區域關聯的使用者來說是持久的。這些設定是特定於區域的,這意味著如果使用者在與主要區域關聯的顯示器上登錄,然後登入與輔助音訊區域關聯的區域,則為第一個區域加載和保留的音量等級將不同於那些用於次要區域的。

處理音量鍵事件

Android 定義了多個用於音量控制的鍵碼,包括KEYCODE_VOLUME_UPKEYCODE_VOLUME_DOWNKEYCODE_VOLUME_MUTE 。預設情況下,Android 將音量鍵事件路由到應用程式。汽車實作應將這些關鍵事件強制傳送給CarAudioService ,然後該服務可以根據需要呼叫setGroupVolumesetMasterMute

若要強制執行此行為,請將config_handleVolumeKeysInWindowManager標誌設為true

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

音量鍵事件目前無法區分它們用於哪個區域,因此假定全部與主音訊區域相關聯。當接收到音量鍵事件時, CarAudioService會透過取得活動播放器的音訊上下文來決定要調整的音量組,然後調整包含與最高優先權音訊上下文關聯的輸出裝置的音量組。優先順序是根據CarVolume.AUDIO_CONTEXT_VOLUME_PRIORITY中定義的固定順序決定的。

淡入淡出和平衡

AudioControl HAL 的兩個版本都包含用於設定車輛淡入淡出和平衡的 API。 CarAudioManager 有對應的系統 API,可將值向下傳遞到 AudioControl HAL。這些 API 需要android.car.permission.CAR_CONTROL_AUDIO_VOLUME

AudioControl API 是:

  • setBalanceTowardRight(float value) 。將揚聲器音量向汽車右側 (+) 或左側 (-) 移動。 0.0 居中,+1.0 完全靠右,-1.0 完全靠左,-1 到 1 範圍之外的值是錯誤的。
  • setFadeTowardFront(float value) - 將揚聲器音量向汽車前部 (+) 或後部 (-) 移動。 0.0 為居中,+1.0 為完全向前,-1.0 為完全向後,-1 到 1 範圍之外的值是錯誤的。

由 OEM 決定如何套用這些值以及如何將它們呈現給使用者。它們可以嚴格應用於媒體或全面應用於所有 Android 聲音。

Android 11 也引入了將音訊效果應用於輸出裝置的支援。這樣,就可以透過適當的輸出裝置上的音訊效果而不是透過這些 API 來管理淡入淡出和平衡。

音訊閃避

當車輛降低一個串流的增益以便可以更清楚地聽到同時播放的另一流時,就會發生音訊閃避。在 AAOS 中,音訊閃避由 HAL 來實現,因為 Android 之外可能存在作業系統無法控制的許多聲音。在 Android 11 中,HAL 可用於做出閃避決策的主要資訊是兩個輸出裝置是否都有活動流。

何時躲避

雖然由各個 OEM 決定其 HAL 如何處理閃避,但我們建議遵循一些通用準則。當兩個應用程式/服務同時持有音訊焦點時,Android 中最常發生多個串流播放。考慮到這一點,請參閱互動矩陣,以了解 Android 何時可以授予並發焦點,以及何時可以同時播放兩個不同的串流。

請記住,Android 混合在一起的任何串流都會在應用任何增益之前完成。因此,與另一個串流同時播放時應迴避的任何串流都應路由到單獨的輸出設備,以便 HAL 在將它們混合在一起之前應用迴避。

建議的逃避行為

以下是我們建議應用閃避的潛在並發互動:

  • EMERGENCY 。除SAFETY外,將所有聲音隱藏或靜音,以確保駕駛員聽到聲音
  • SAFETY 。避開除EMERGENCY外的所有聲音,以確保駕駛員聽到聲音
  • NAVIGATION 。除SAFETYEMERGENCY外,迴避一切
  • CALL 。除了SAFETYEMERGENCYNAVIGATION之外,迴避一切
  • VOICE 。鴨子CALL_RING
  • 由 OEM 決定活動VEHICLE_SOUNDS的重要性,以及是否應該迴避其他聲音以確保駕駛者聽到它們。
  • MUSICANNOUNCEMENT應該被一切事物所掩蓋。主要的例外是觸摸互動音,目前作為SYSTEM_SOUND播放

躲避時的其他注意事項

某些應用程式/服務(例如導航或助手)可能會使用多個玩家來完成其操作。 OEM 應該避免根據串流資料停止通過這些輸出裝置的時間過於積極地取消閃避,以確保使用者在導航或助理應用程式開始下一次播放時不會立即讓媒體恢復到最大音量,然後又重新降低音量。

對於具有多個聲場且隔離效果足夠好的車輛,還可以選擇將音訊路由到汽車的不同區域,而不是迴避。例如,導航指令可以發送到駕駛員的頭枕揚聲器,同時音樂繼續以正常音量在整個機艙內播放。

安全關鍵聲音

雖然 Android 11 引進了HAL 音訊焦點 API ,但仍需由 HAL 來確保安全關鍵聲音優先於其他聲音。即使 HAL 持有USAGE_EMERGENCY的音訊焦點,也不能保證 Android 中的應用程式和服務不會播放聲音。由 HAL 決定在播放安全關鍵聲音時應混合或靜音來自 Android 的哪些串流。

配置音量設定 UI

AAOS 將磁碟區設定 UI 與磁碟區組配置分開(可依照設定卷組中的描述進行覆寫)。這種分離可確保將來卷組配置發生變更時無需進行任何變更。

在汽車設定 UI 中, packages/apps/Car/Settings/res/xml/car_volume_items.xml檔案包含與每個定義的AudioAttributes.USAGE關聯的 UI 元素(標題和圖示資源)。該文件透過使用與每個卷組中包含的第一個識別的用法相關聯的資源來合理地呈現所定義的VolumeGroups

例如,以下範例將 VolumeGroup 定義為同時包含voice_communicationvoice_communication_signalling 。汽車設定 UI 的預設實作使用與voice_communication關聯的資源呈現 VolumeGroup,因為這是檔案中的第一個資源。

<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中聲明。音量設定 UI 使用以下基於 VolumeGroup 的 CarAudioManager API:

  • getVolumeGroupCount()了解應繪製多少個控制項。
  • getGroupMinVolume()getGroupMaxVolume()取得下限和上限。
  • getGroupVolume()取得目前音量。
  • registerVolumeChangeObserver()以取得有關音量變化的通知。