音訊控制 HAL

Android 9 導入音訊控制 HAL 支援與汽車相關的音訊用途自 Android 手機起 14,音訊控制 HAL 支援:

  • 淡出和平衡
  • HAL 音訊焦點要求
  • 裝置靜音與降低背景音量
  • 音訊裝置增益
  • 音訊通訊埠設定變更

圖 1 是高階汽車音響服務架構的概要總覽。 汽車音訊服務會與音訊控制 HAL 進行通訊

設定多區域音訊

圖 1. 設定多區域音訊。

音訊淡出和平衡

Android 導入了 HIDL 音訊控制 HAL 版本 1 9 鍵:在車輛使用時支援淡出和平衡音訊 用途除了 Android 中提供的一般音效, 機制可讓系統應用程式 CarAudioManager API:

class CarAudioManager {
       /**
       *   Adjust the relative volume in the front vs back of the vehicle cabin.
       *
       *   @param value in the range -1.0 to 1.0 for fully toward the back through
       *   fully toward the front. 0.0 means evenly balanced.
       */
       @SystemApi
       @RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
       public void setFadeTowardFront(float value);

       /**
       *   Adjust the relative volume on the left vs right side of the vehicle cabin.
       *
       *   @param value in the range -1.0 to 1.0 for fully toward the left through
       *   fully toward the right. 0.0 means evenly balanced.
       */
       @SystemApi
       @RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
       public void setBalanceTowardRight(float value);
}

呼叫這些 API 後,系統會呼叫各個音訊控制項 HAL API :

interface IAudioControl {
       /**
       *   Control the right/left balance setting of the car speakers.
       */
       oneway setBalanceTowardRight(float value);

       /**
       *   Control the fore/aft fade setting of the car speakers.
       */
       oneway setFadeTowardFront(float value);
}

此 API 適用於所有音訊控制 HAL,包括新的 AIDL HAL 介面。

HAL 提出的音訊焦點要求

AAOS 與 Android 類似,都必須仰賴使用者主動提供音訊應用程式 著重於管理車輛音訊播放。焦點資訊會用於管理 控制音量和降低背景音量。因此,我們會再繼續 強化音訊焦點,並以更優異的方式,將車輛專屬聲音融入其中 Android 體驗,導入了下列音訊屬性 Android 11:

  • EMERGENCY
  • SAFETY
  • VEHICLE_STATUS
  • ANNOUNCEMENT

除了這項變更外,我們還針對原始音訊新增一項機制 參與音訊焦點要求因此,HIDL 音訊 控制 HAL 版本 2 的用意是允許來自最初的焦點要求 。

interface IAudioControl {
       /**
       *   Registers focus listener to be used by HAL for requesting and
       *   abandoning audio focus.
       *   @param listener the listener interface
       *   @return closeHandle A handle to unregister observer.
       */
       registerFocusListener(IFocusListener listener)
       generates (ICloseHandle closeHandle);

       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   @param usage The audio usage associated with the focus change
       *   @param zoneId The identifier for the audio zone that the HAL is
       *   playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred
       */
       oneway onAudioFocusChange(bitfield<AudioUsage> usage, int32_t zoneId,
       bitfield<AudioFocusChange> focusChange);
}

其中 IFocusListener 定義如下:

interface IFocusListener {
       /**
       *   Called whenever HAL is requesting focus as it is starting to play
       *   audio of a given usage in a specified zone.
       *
       *   @param usage The audio usage associated with the focus request
       *    {@code AttributeUsage}
       *   @param zoneId The identifier for the audio zone where the HAL is
       *    requesting focus
       *   @param focusGain The AudioFocusChange associated with this request.
       */
       oneway requestAudioFocus(bitfield<AudioUsage> usage,
       int32_t zoneId, bitfield<AudioFocusChange> focusGain);
       /**
       *   Called whenever HAL is abandoning focus as it is finished playing audio
       *   of a given usage in a specific zone.
       *
       *   @param usage The audio usage for which the HAL is abandoning focus
       *    {@code AttributeUsage}
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       */
       oneway abandonAudioFocus(bitfield<AudioUsage> usage, int32_t zoneId);
}

上述 API 可用於從 HAL、 。為回應車輛音訊焦點 然後以非同步方式將結果轉送至 IAudioControl#onAudioFocusChange 方法。

這個 API 也可用來監控音訊焦點要求的變更, 源自音訊控制 HAL一般來說,任何站立的音訊焦點 系統會將 HAL 發出的要求視為「有效」,但與音訊焦點不同 要求,並且只播放對應的有效音軌 一律視為有效。

將 HIDL 遷移至 AIDL 音訊控制 HAL

隨著 AIDL 的問世,以及 Android 需要的遷移作業 12 (如要瞭解詳情,請參閱 AIDL 針對 HALs),音訊控制 HAL 是 遷移至 AIDL如為現有的 HIDL 音訊控製版本 2 API,則遷移 需要小幅調整現有方法:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   @param usage The audio usage associated with the focus change
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone that the HAL is
       *        playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred.
       */
       oneway void onAudioFocusChange(in String usage, in int zoneId,
              in AudioFocusChange focusChange);
       /**
       *   Registers focus listener to be used by HAL for requesting and
       *   abandoning audio focus.
       *   @param listener the listener interface.
       */
       oneway void registerFocusListener(in IFocusListener listener);
       /**
       *   Control the right/left balance setting of the car speakers.
       */
       oneway void setBalanceTowardRight(in float value);
       /**
       *   Control the fore/aft fade setting of the car speakers.
       */
       oneway void setFadeTowardFront(in float value);
}

以及對應的 IFocusListener

       interface IFocusListener {
       /**
       *   Called whenever HAL is abandoning focus as it is finished playing audio
       *   of a given usage in a specific zone.
       *
       *   @param usage The audio usage for which the HAL is abandoning focus
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone that the HAL
       *        abandoning focus
       */
       oneway void abandonAudioFocus(in String usage, in int zoneId);
       /**
       *   Called whenever HAL is requesting focus as it is starting to play audio
       *        of a given usage in a specified zone.
       *
       *   @param usage The audio usage associated with the focus request
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone where the HAL is
       *        requesting focus
       *   @param focusGain The AudioFocusChange associated with this request.
       */
       oneway void requestAudioFocus(in String usage, in int zoneId,
              in AudioFocusChange focusGain);
}

音量群組靜音

Android 12 導入了音量群組靜音功能, 在使用者與音訊互動時,提供更完整的靜音控制項。這個 可讓音訊控制 HAL 接收經車輛攔截的靜音事件 音訊服務

如要啟用這項功能,原始設備製造商 (OEM) 必須進行 audioUseCarVolumeGroupMuting 設定 到 true 的車用服務 config.xml

<!-- Configuration to enable muting of individual volume groups.
If this is set to false, muting of individual volume groups is disabled,
instead muting will toggle master mute. If this is set to true, car volume
group muting is enabled and each individual volume group can be muted separately. -->
<bool name="audioUseCarVolumeGroupMuting">true</bool>

在 Android 13 以下版本中,您必須覆寫設定 畫面上可以看到 packages/services/Car/service/res/values/config.xml (詳情請參閱 使用資源自訂建構 疊加層)。從 Android 轉移 13,您可以使用執行階段資源疊加層,將 設定值詳情請參閱「變更應用程式資源的值」 在執行階段期間

系統應用程式可以使用 CarAudioManager#isAudioFeatureEnabled API。傳入的參數必須是 CarAudioManager.AUDIO_FEATURE_VOLUME_GROUP_MUTING 常數。此方法會傳回 如果裝置已啟用該功能,則為 true,否則為 false

除了啟用 audioUseCarVolumeGroupMuting 功能外,AIDL 也為 音訊控制 HAL 必須導入音量群組靜音機制:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in output devices that the HAL should apply
       *   muting to.
       *
       *   This will be called in response to changes in audio mute state for each
       *   volume group and will include a {@link MutingInfo} object per audio
       *   zone that experienced a mute state event.
       *
       *   @param mutingInfos an array of {@link MutingInfo} objects for the audio
       *   zones where audio mute state has changed.
       */
       oneway void onDevicesToMuteChange(in MutingInfo[] mutingInfos);
}

靜音資訊包含與音訊系統相關的靜音資訊:

parcelable MutingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be muted.
       */
       String[] deviceAddressesToMute;
       /**
       *   List of addresses for audio output devices that were previously be
       *   muted and should now be unmuted.
       */
       String[] deviceAddressesToUnmute;
}

基於以下因素,AAOS 有兩種不同的靜音機制:

  • 使用音訊的重要事件 KEYCODE_VOLUME_MUTE

  • 使用車輛音訊管理員的靜音 API,直接撥打車輛音訊服務。 CarAudioManager#setVolumeGroupMute

啟用時,這兩項機制都會觸發將通話靜音,轉變成音訊控制 HAL。

汽車音訊降低音量

Android 12 導入了汽車音響降低功能,以最佳化音訊並行的操控方式 音訊串流播放。讓原始設備製造商 (OEM) 能自行設計繪圖 根據車輛的實體音訊設定和目前播放條件決定的行為 狀態;由汽車音訊服務決定。

降低背景音量是以音訊焦點堆疊的變更為基礎。每當 對焦變更發生 (無論是對焦點要求或失去焦點),音訊 控管 HAL 控制項與汽車音量群組靜音支援 (汽車) 類似 你可以使用 audioUseHalDuckingSignals 設定旗標啟用「降低其他應用程式音量」功能:

<!-- Configuration to enable IAudioControl#onDevicesToDuckChange API to
inform HAL when to duck. If this is set to true, the API will receive signals
indicating which output devices to duck as well as what usages are currently
holding focus. If set to false, the API will not be called. -->
<bool name="audioUseHalDuckingSignals">true</bool>

如要啟用此功能,AIDL 音訊控制 HAL 必須導入相關的 邏輯運算子,並參考從車輛音訊服務接收到的訊號:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in output devices that the HAL should apply
       *   ducking to.
       *
       *   This will be called in response to changes in audio focus, and will
       *   include a {@link DuckingInfo} object per audio zone that experienced
       *   a change in audo focus.
       *
       *   @param duckingInfos an array of {@link DuckingInfo} objects for the
       *   audio zones where audio focus has changed.
       */
       oneway void onDevicesToDuckChange(in DuckingInfo[] duckingInfos);
}

相關音訊系統資訊包含在「降低其他應用程式音量」中 每個 ACL 都由一或多個項目組成 而這些項目包含兩項資訊

parcelable DuckingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be ducked.
       */
       String[] deviceAddressesToDuck;
       /**
       *   List of addresses for audio output devices that were previously be
       *   ducked and should now be unducked.
       */
       String[] deviceAddressesToUnduck;
       /**
       *   List of usages currently holding focus for this audio zone.
       */
       String[] usagesHoldingFocus;
}

除了裝置地址中的車輛音訊設定資訊以外 針對 屬性的使用會一直聚焦於注意力。這項資料的用意是向 音訊屬性使用的預設音訊系統。

此為必要步驟,因為在汽車音訊設定中,有多個音訊 可指派給單一裝置,沒有額外的 資訊,系統並不清楚哪些是正在使用哪些用量。

AIDL 音訊控制 HAL 2.0

為更新 API 及提供新功能,AIDL 音訊控制 HAL 已在 Android 13 中更新為 2.0 版:

  • 使用PlaybackTrackMetadata的語音焦點功能
  • 音訊增益

android.hardware.audio.common 對播放中繼資料的定義如下:

parcelable PlaybackTrackMetadata {
       AudioUsage usage = INVALID;
       AudioContentType contentType = UNKNOWN;
       float gain;
       AudioChannelLayout channelMask;
       AudioDevice sourceDevice;
       String[] tags;
}

其餘功能都保留, 與音訊焦點變更方法相關的例外狀況,如下所述 變更音訊焦點的方法

含播放曲目中繼資料的音訊控制焦點

為了向 HAL 下方的音訊系統公開更多資訊,更新現在會公開 PlaybackTrackMetadata。具體來說,音訊控制 HAL 以 新方法:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   The HAL is not required to wait for a callback of AUDIOFOCUS_GAIN
       *   before playing audio, nor is it required to stop playing audio in the
       *   event of a AUDIOFOCUS_LOSS callback is received.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL is
       *    playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred.
       */
       oneway void onAudioFocusChangeWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId,
       in AudioFocusChange focusChange);
}

有類似且對應的變更會對 IFocusListener 進行以下變更:

       /**
       *   Called to indicate that the audio output stream associated with
       *   {@link android.hardware.audio.common.PlaybackTrackMetadata} is
       *   abandoning focus as playback has stopped.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       */
       oneway void abandonAudioFocusWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId);
       /**
       *   Called to indicate that the audio output stream associated with
       *   {@link android.hardware.audio.common.PlaybackTrackMetadata} has taken
       *   the focus as playback is starting for the corresponding stream.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       *   @param focusGain The focus type requested.
       */
       oneway void requestAudioFocusWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId,
       in AudioFocusChange focusGain);
}

變更音訊焦點的方法

上述焦點作業的運作方式與音訊 HAL 發出焦點要求。只有播放曲目中繼資料 資訊,以及音訊屬性的使用情況。一般而言,除非 我們需要透過音軌中繼資料提供的資訊,而更新後的 Android 控制 HAL 可以繼續使用先前的方法。

HAL 開發人員選擇不提供支援時 IAudioControl#onAudioFocusChangeWithMetaData,此方法應傳回結果 收到 UNKNOWN_TRANSACTION 錯誤,如「使用版本化介面」所述 方法

音訊服務會先呼叫 onAudioFocusChangeWithMetaData 並 如果 UNKNOWN_TRANSACTION,則使用 onAudioFocusChange 方法重試 也會失敗

汽車音響,搭配播放曲目中繼資料

AIDL 音訊控制 HAL 2.0 版將播放曲目中繼資料新增至 降低背景音量:

parcelable DuckingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be ducked.
       */
       String[] deviceAddressesToDuck;
       /**
       *   List of addresses for audio output devices that were previously be
       *   ducked and should now be unducked.
       */
       String[] deviceAddressesToUnduck;
       /**
       *   List of usages currently holding focus for this audio zone.
       */
       String[] usagesHoldingFocus;
       /**
       *   List of output stream metadata associated with the current focus
       *   holder for this audio zone
       */
       @nullable PlaybackTrackMetadata[] playbackMetaDataHoldingFocus;
}

usagesHoldingFocus 已淘汰,開發人員現在應使用 playbackMetaDataHoldingFocus:判斷音訊屬性用途和其他狀態 以及音訊資訊也就是說,usagesHoldingFocus 參數仍包含 ,直到這個選項正式移除為止。

音訊增益回呼

讓 Android 中的 AAOS 更容易在 HAL 下方變更音訊 13,我們加入了一項相關功能 音訊。 機制會公開音訊增益量指數變化,並說明原因 增益已變更:

  • 封鎖或靜音的限制
  • 限制
  • 注意力限制

這些異動會從 HAL 下方曝露出這些限制: 最後則是在系統 UI 應用程式上通知使用者。 後者則是進一步展開可能的系統 UI Android 14 可讓系統 UI 應用程式更容易取得這項資訊 透過磁碟區群組資訊回呼機制

音訊控制 HAL API 會註冊取得回呼,如下所示:

interface IAudioControl {
       /**
       *   Registers callback to be used by HAL for reporting unexpected gain(s)
       *    changed and the reason(s) why.
       *
       *   @param callback The {@link IAudioGainCallback}.
       */
       oneway void registerGainCallback(in IAudioGainCallback callback);
}

IAudioGainCallback 的定義如下:

interface IAudioGainCallback {
       /**
       *   Used to indicate that one or more audio device port gains have changed,
       *   i.e. initiated by HAL, not by CarAudioService.
       *   This is the counter part of the
       *   {@link onDevicesToDuckChange}, {@link onDevicesToMuteChange} and,
       *   {@link setAudioDeviceGainsChanged} APIs.
       *
       *   @param reasons List of reasons that triggered the given gains changed.
       *   @param gains List of gains affected by the change.
       */
       void onAudioDeviceGainsChanged(in Reasons[] reasons,
       in AudioGainConfigInfo[] gains);
}

如 API 說明文件所強調, 並將車內音訊服務傳送到音訊控制 HAL從 音訊控制 HAL,車輛音訊服務會回應相應的動作 (例如封鎖、限製或提高獲利指數)。

HAL 會決定呼叫 API 的時機,主要目的是回報 取得索引狀態車輛音響系統受法規規範 應採取必要動作,並透過回呼回報資訊給 供車輛音訊服務使用。例如,為了顯示 以便傳達給使用者

AIDL 音訊控制 HAL 3.0

Android 14 AIDL 音訊控制 HAL 版本為 更新至 3.0 版,更新 API,提供更優異的音訊增益 索引功能音訊控制 HAL API 可讓音訊服務 設定及取消設定 IModuleChangeCallback

interface IAudioControl {
       /**
       *   Sets callback with HAL for notifying changes to hardware module
       *   (that is: {@link android.hardware.audio.core.IModule}) configurations.
       *
       *   @param callback The {@link IModuleChangeCallback} interface to use
       *    use when new updates are available for
       */
       void setModuleChangeCallback(in IModuleChangeCallback callback);
       /**
       *   Clears module change callback
       */
       void clearModuleChangeCallback();
}

setModuleChangeCallback 是由車輛音訊服務登錄,而且當 就會啟動或從錯誤復原。例如音訊控制 汽車音訊服務收到的 HAL 繫結器死亡通知。音訊 控制項 HAL 實作應取代所有現有的模組變更回呼 呼叫 API 時

如果是 clearModuleChangeCallback API,實作應清除 現有的回呼,即使不存在,也不會執行任何動作。在 BERT 模型中 音訊控制實作,以為回呼註冊死亡觀察器 然後,如果觸發繫結器死亡,即可清除回呼。

IModuleChangeCallback 的定義如下:

oneway interface IModuleChangeCallback {
       /**
       *   Used to indicate that one or more {@link AudioPort} configs have
       *   changed. Implementations MUST return at least one AudioPort.
       *
       *   @param audioPorts list of {@link AudioPort} that are updated
       */
       void onAudioPortsChanged(in AudioPort[] audioPorts);
}

如果車輛音訊服務登錄了模組變更回呼, 準備透過 onAudioPortChanged API 接收音訊通訊埠變更。 API 可用於初始化音訊系統的音量增益 註冊回呼。如要進行其他動態增益變更,則可呼叫 API 。系統會套用對應變更,並更新車輛音訊服務 。