音訊焦點

在啟動邏輯流之前,應用程式使用與邏輯流相同的音訊屬性請求音訊焦點。應用程式必須考慮焦點損失,才能在汽車用例中按預期執行。

雖然建議發送焦點請求,但係統並不會強制執行。因此,請將焦點視為播放過程中間接控制和避免衝突的手段,而不是主要的音訊控制機制。車輛不應依賴聚焦系統來操作音頻子系統。

聚焦互動

為了支援 AAOS,音訊焦點請求是根據請求的CarAudioContext和當前焦點持有者之間的預先定義互動來處理的。互動可分為三種:

  • 獨家的
  • 拒絕
  • 並行

獨家互動

這是 Android 最常用的互動模型。

獨佔互動中,一次只允許一個應用程式保持焦點。因此,傳入的焦點請求將被授予焦點,而現有的焦點持有者將失去焦點。由於兩個應用程式都播放媒體,因此只允許一個應用程式保持焦點。因此,新啟動的應用程式的焦點請求將傳回AUDIOFOCUS_REQUEST_GRANTED ,而目前播放音樂的應用程式會收到焦點變更事件,其狀態為與所發出的請求類型相對應的遺失狀態。

拒絕互動

對於拒絕交互,傳入的請求總是被拒絕。例如,在通話過程中嘗試播放音樂時。在這種情況下,如果撥號器保持呼叫的音訊焦點,並且第二個應用程式請求焦點播放音樂,則音樂應用程式會收到AUDIOFOCUS_REQUEST_FAILED作為對請求的回應。由於焦點請求被拒絕,因此不會將焦點遺失分派給目前焦點持有者。

並發交互

AAOS 的獨特之處在於並發互動。這使得請求車內音訊焦點的應用程式能夠與其他應用程式同時保持焦點。要發生並發交互,必須滿足以下條件。這:

如果滿足這些條件,則焦點請求將傳回AUDIOFOCUS_REQUEST_GRANTED ,而目前焦點持有者的焦點沒有變化。但是,如果當前焦點持有者選擇接收鴨子事件或在鴨子被鴨子時暫停,則當前焦點持有者將失去焦點,就像獨佔互動時發生的那樣。

處理並發流

雖然並發互動有多種用途,但在跨輸出裝置的硬體層級進行混合和閃避時要小心。我們強烈建議將允許同時播放的CarAudioContext路由到不同的輸出設備。

透過為並發流提供單獨的輸出設備,HAL 可以在混合流之前迴避其中一個流,或者將物理流路由到車輛中的不同揚聲器。如果邏輯流在 Android 中混合,則增益不會改變並作為相同物理流的一部分提供。

例如,當同時傳送導航和媒體時,可以暫時降低(或迴避)媒體串流的增益,以便更清楚地聽到導航指令。或者,導航串流可以路由到駕駛員側揚聲器,同時媒體繼續在車內的其餘部分播放。

互動矩陣

下表顯示了CarAudioService定義的交互矩陣。每行代表目前焦點持有者的CarAudioContext ,每列代表傳入請求的 CarAudioContext。

例如,當音樂媒體應用程式在導航應用程式請求焦點時保持焦點時,假設滿足並發互動的其他標準,則矩陣指示兩個互動可以同時播放。

由於同時進行交互,因此可能有多個焦點持有者。在這種情況下,在確定要套用什麼互動之前,會將傳入的焦點請求與每個目前焦點持有者進行比較。在這種情況下,最保守的互動獲勝。拒絕,然後排他,最後並發。

音訊聚焦互動矩陣

圖 1.音訊焦點互動矩陣。

在 Android 11 中,引入了新的用戶設置,允許用戶更改導航和電話之間的互動行為。設定後, android.car.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL會將傳入的NAVIGATION焦點請求與目前CALL焦點持有者之間的互動從並發變更為拒絕。如果使用者希望導航指令不中斷通話,則可以啟用此設定。這是為用戶保留的,並且可以動態設置,以便後續的焦點請求遵循新的設置。

可延遲的音訊焦點

在 Android 11 中,AAOS 增加了對請求延遲音訊焦點的支援。當非瞬態焦點請求與目前焦點持有者的互動通常會導致它們被拒絕時,這允許延遲非瞬態焦點請求。一旦焦點發生變化導致延遲的請求可以獲得焦點,該請求就會被授予。

延遲音訊焦點請求的規則

  • 僅適用於非暫時性請求。只能對非瞬態來源發出延遲請求,以避免瞬態聲音在相關後很長一段時間內播放。

  • 一次只能延遲一個請求。如果在已有延遲請求的情況下發出可延遲請求,則原始延遲請求會收到AUDIOFOCUS_LOSS變更事件,而新請求會收到AUDIOFOCUS_REQUEST_DELAYED同步回應。

  • 可延遲請求必須具有OnAudioFocusChangeListener一旦請求被延遲,偵聽器將用於在請求最終被授予 ( AUDIOFOCUS_GAIN ) 或稍後被拒絕 ( AUDIOFOCUS_LOSS ) 時通知請求者。

請求延遲焦點

要建置可以延遲的請求:

  1. 使用AudioFocusRequest.Builder#setAcceptsDelayedFocusGain

    mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener();
    
    mDelayedFocusRequest = new AudioFocusRequest
         .Builder(AudioManager.AUDIOFOCUS_GAIN)
         .setAudioAttributes(mMusicAudioAttrib)
         .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener)
         .setForceDucking(false)
         .setWillPauseWhenDucked(false)
         .setAcceptsDelayedFocusGain(true)
         .build();
    
  2. 發出請求時,處理AUDIOFOCUS_REQUEST_DELAYED回應:

    int delayedFocusRequestResults = mAudioManager.requestAudioFocus(mDelayedFocusRequest);
    if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        // start audio playback
        return;
    }
    if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
         // audio playback delayed to audio focus listener
         return;
    }
    
  3. 當請求延遲時,焦點偵聽器會處理焦點的變化:

    private final class MediaWithDelayedFocusListener implements
    OnAudioFocusChangeListener {
           @Override
           public void onAudioFocusChange(int focusChange) {
               synchronized (mLock) {
                   switch (focusChange) {
                       case AudioManager.AUDIOFOCUS_GAIN:
                           … // Start focus playback
                       case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                           … // Pause media transiently
                       case AudioManager.AUDIOFOCUS_LOSS:
                           … // Stop media
    

多區域焦點管理

對於具有多個音訊區域的車輛,每個區域的音訊焦點都是獨立管理的。因此,對一個區域的請求不會考慮其他區域中持有焦點的內容,也不會導致其他區域中的焦點持有者失去焦點。這樣,主艙的焦點可以與後座娛樂系統分開管理,從而不會因焦點改變到另一個區域而中斷一個區域的音訊播放。

對於所有應用程序, CarAudioService會自動管理焦點。焦點請求的音訊區域由其關聯的UserIdUID確定(有關詳細信息,請參閱音訊路由)。

同時從多個區域請求音頻

如果應用程式想要同時在多個區域中播放音頻,則必須透過在捆綁包中包含AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID來請求每個區域的焦點:

//Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
Bundle bundle = new Bundle();
bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID,
               zoneId);

AudioAttributes attributesWithZone = new AudioAttributes.Builder()
     .setUsage(AudioAttributes.USAGE_MEDIA)
     .addBundle(bundle)
     .build();

//Create focus request using built attributesWithZone

此捆綁參數允許請求者覆蓋自動音訊區域對應以改為使用指定的區域 ID。因此,應用程式可以針對不同的音訊區域發出單獨的請求。

HAL 音訊焦點

從 Android 11 開始,HAL 能夠代表外部串流請求焦點。雖然可選,但強烈鼓勵使用這些 API,以使外部聲音成為 Android 生態系統的最佳參與者並提供無縫的用戶體驗。

HAL 最終決定哪些聲音應優先。就此而言,無論 HAL 是否被授予音訊焦點,都應播放緊急和安全關鍵聲音,並且即使 HAL 失去音訊焦點,也應繼續適當播放。對於政府法規要求的任何聲音也是如此。

在播放緊急或安全關鍵聲音時,HAL 應酌情主動將 Android 串流靜音,以確保清晰地聽到它們。

音訊控制@2.0

AudioControl HAL 2.0 版本引入了這些新 API:

應用程式介面目的
IAudioControl#registerFocusListener向 AudioControl HAL 註冊IFocusListener的實例。此偵聽器使 HAL 能夠請求和放棄音訊焦點。 HAl 提供了一個ICloseHandle實例,供 Android 使用來取消註冊偵聽器。
IAudioControl#onAudioFocusChange通知 HAL HAL 透過IFocusListener發出的焦點請求的狀態變化,包括對初始焦點請求的回應。
IFocusListener#requestAudioFocus代表 HAL 請求針對指定用途、區域 ID 和焦點增益類型的焦點。
IFocusListener#abandonAudioFocus放棄指定用途和區域 ID 的現有 HAL 焦點請求。

HAL 可以同時有多個焦點請求,但僅限於每次使用和區域 ID 配對一個請求。 Android 假設 HAL 在發出請求後立即開始播放聲音以供使用,並繼續這樣做,直到放棄焦點。

除了registerFocusListener之外,這些請求是確保 Android 在處理焦點請求時不會延遲 HAL 的oneway 。 HAL應該等到獲得焦點才播放安全關鍵的聲音。 HAL 可以選擇透過IAudioControl#onAudioFocusChange監聽並回應音訊焦點的變化。

OEM汽車音響聚焦服務

在 Android 14 中,AAOS 引入了汽車 OEM 插件服務,以實現某些汽車組件的可設定性。對於汽車音訊插件服務,插件服務允許 OEM 管理汽車音訊服務攔截的焦點請求。這使得原始設備製造商在按照規則和法規的要求管理重點方面具有更大的靈活性。因此,音訊焦點互動可能因製造商和地區而異。音頻焦點的基本前提仍然成立,即應用程式仍應請求焦點以更好地管理音頻,以增強用戶體驗。一般來說,某些規則仍然適用於應用程式的音訊焦點請求:

  • 在沒有任何站立的情況下,高優先級音訊焦點(包括電話呼叫、緊急警報或安全通知)應用程式應該能夠暫時或永久獲得音訊焦點。

  • 當媒體焦點活躍時:

    • 請求呼叫使用焦點的應用程式應該能夠同時或獨佔地接收呼叫。

    • 請求導航使用焦點的應用程式應該能夠同時或單獨接收導航焦點。

    • 請求助理使用焦點的應用程式應該能夠同時或單獨接收使用焦點。

  • 當高優先級音訊焦點(包括電話、緊急警報或安全通知)應用程式處於活動狀態時,任何傳入的延遲音訊焦點請求都應根據需要授予或延遲。

雖然上述建議並不詳盡,但如果不存在活動的高優先級聲音,它們可以幫助請求焦點的應用程式獲得焦點。即使高優先級聲音處於活動狀態,仍應遵守延遲的焦點請求,並且應能夠在高優先級聲音停止時獲得焦點。