Android Automotive OS (AAOS) 是以 Android 核心音訊堆疊為基礎, 輔助將應用在車輛的資訊娛樂系統上。 AAOS 負責資訊娛樂聽覺,例如媒體、導航、 ,但就使用 嚴格的可用性與時間規定AAOS 會提供信號 協助車輛管理音訊的機制,最終取決於車輛 讓駕駛人看到應該播放的音效 乘客,確保安全重要聲響和監管音效 不中斷
Android 會管理車輛的媒體體驗,以及外部媒體來源 例如電台調音器應由能夠處理音訊的應用程式 來源的焦點和媒體重要事件
Android 11 針對汽車相關音訊做了以下變更 支援服務:
Android 音效與串流
Automotive 音訊系統會處理下列音訊和串流內容:
圖 1. 以串流為主的架構圖
Android 會管理 Android 應用程式發出的音效,控管這些應用程式 並透過 HAL 輸出裝置 音效:
- 邏輯串流,稱為核心音訊來源 命名法則加上 Audio 屬性 (音訊屬性) 標記。
- 實體串流,稱為核心音訊的裝置 雜訊,卻沒有背景資訊。
為提高可靠性,外來聲音 (有獨立音訊來源) 安全提示 (例如座椅警告鈴聲) 等來源是在 Android 以外的地方管理,位於 HAL 或獨立硬體。系統實作者必須提供混合器, 接受 Android 提供的一或多個聲音輸入串流,然後將這些音訊 配合要求本身的外部聲音來源播放音樂 。
HAL 實作和外部混合器負責 安全重要外部聲響,並用於混和 Android 提供的 並轉送到適合的揚聲器
Android 音效
應用程式可能有一或多個播放器透過標準 Android 互動 API (例如 AudioManager 用於焦點控製或 MediaPlayer ) 輸出一或多個邏輯串流。這項資料 可以是單聲道或 7.1 環場音效,但會轉送並視為 單一來源。應用程式串流與 AudioAttributes 相關聯 讓系統提示音訊的表示方式。
邏輯串流透過 AudioService 傳送,並轉送至 其中一個) 可用實體輸出串流,而每個串流都是 AudioFlinger 的混合程式混合音訊屬性後 但已無法在實體串流中播放。
然後將每個實體串流傳送到音訊 HAL 以便顯示 因此,在硬體方面在車用應用程式中,算繪硬體可以是本機轉碼器 (與行動裝置類似) 或車輛實體的遠端處理器 更是如此無論採用哪種方式,都是由音訊 HAL 實作負責 實際的樣本資料並使該資料變為可聽狀態
外部串流
不得使用 Android 轉送的音效串流 (用於認證或 時間可能),因此直接傳送給外部混音器。自 Android 11 起, HAL 已可要求集中在外部聲響通知 Android 以便採取適當行動,例如暫停媒體或防止 用於協助其他員工
如果外部串流是應與音效互動的媒體來源 環境 (例如在載入完成後停止播放 MP3 內容 外部調諧器開啟時,外部串流應以 Android 應用程式。這類應用程式會代表媒體來源要求音訊焦點 並會回應焦點通知 配合 Android 焦點,視需要開始/停止外部來源 政策。應用程式也負責處理媒體重要事件,例如 播放/暫停。控管這類外部裝置的其中一種機制是 HwAudioSource。
輸出裝置
音訊 HAL 等級:裝置類型:AUDIO_DEVICE_OUT_BUS
提供用於車輛音響系統的一般輸出裝置。公車
裝置支援可定址的連接埠 (每個連接埠都是
且應該是 中唯一支援的輸出裝置類型。
例如車輛
系統實作時,可在下列位置為所有 Android 音效使用一個公車連接埠
在這種情況下,Android 會結合所有元素並在單一串流中傳送。
或者,HAL 可以為每個 CarAudioContext
提供一個公車連接埠,以便
並行傳送這使 HAL 可以
實作以視需求混合及消除不同聲音
將音訊情境指派給輸出裝置是透過以下方式完成:
car_audio_configuration.xml
。
麥克風輸入
擷取音訊時,音訊 HAL 會收到 openInputStream
呼叫,其中包括 AudioSource
引數,指出
應該處理麥克風輸入
VOICE_RECOGNITION
來源
(具體來說是 Google 助理) 預期的立體聲麥克風串流,
消除回音 (如有),但不套用其他處理程序。
Google 助理應一律採用波束成形技術。
多聲道麥克風輸入
如要透過含有超過兩個聲道 (立體聲) 的裝置擷取音訊,請使用
頻道索引遮罩,而不採用位置索引遮罩 (例如
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 起,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
。此外,如果
會在建構工具上設定系統使用量和用量
IllegalArgumentException
建構時。
查看哪些用量與 AudioAttributes
相關聯
呼叫 AudioAttributes#getSystemUsage
。
此方法會傳回相關的用量或系統用量。
音訊情境
為簡化 AAOS 音訊的設定,我們將類似使用方式分組
放入 CarAudioContext
。這些音訊情境會用於
CarAudioService
:定義轉送、音量群組和音訊焦點
以自動化做法管理成本
Android 11 的音訊情境如下:
CarAudioContext | 相關聯的屬性使用資訊 |
---|---|
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 開始的多區域音訊功能可讓原始設備製造商 (OEM) 設定音訊 到個別可用區中每個可用區都是車輛內部的一組裝置 含有專屬磁碟區群組、情境路徑設定和焦點 以自動化做法管理成本透過這種方式,將主機櫃可以設為單一音訊 區域,而後置顯示器的耳機插孔則設為第二個區域。
區域定義為 car_audio_configuration.xml
的一部分。
CarAudioService
會讀取設定,並協助 AudioService
根據相關聯的可用區轉送音訊串流每個可用區都仍會定義
基於結構定義和應用程式 UID 的轉送規則。當玩家
CarAudioService
會決定玩家在哪個可用區
或與 AudioFlinger 的使用情況有關
應將音訊轉送至
每個音訊區域的焦點也會分開維護。這樣一來,
在不同可用區中獨立產生音訊
幹擾彼此,同時讓應用程式仍會尊重
成為區域內的焦點CarZonesAudioFocus
範圍:
CarAudioService
負責管理
可用區
圖 2. 設定多區域音訊
音訊 HAL
Automotive 音訊導入作業仰賴標準 Android Audio HAL。 包括:
IDevice.hal
。建立輸入和輸出串流。 會處理主要磁碟區和靜音,並使用:createAudioPatch
。在裝置之間建立外部修補程式。IDevice.setAudioPortConfig()
可為每個實體串流提供音量。
IStream.hal
。除了輸入和輸出變化版本 管理與硬體之間的音訊樣本串流。
Automotive 裝置類型
以下裝置類型與汽車平台相關。
裝置類型 | 說明 |
---|---|
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 |
透過藍牙接收的音樂。 |
AUDIO_DEVICE_IN_TELEPHONY_RX |
用於與手機相關聯的行動網路無線電接收音訊 呼叫。 |
設定音訊裝置
Android 可以看到的音訊裝置必須
/audio_policy_configuration.xml
,其中包含下列元件:
- 模組名稱。支援「primary」(適用於汽車用途)、
「A2DP」、「remote_submix」和「USB」。模組名稱和對應的音訊
驅動程式應編譯為
audio.primary.$(variant).so
。 - devicePorts。包含所有輸入和輸出的裝置描述元清單 裝置 (包括永久連接裝置和卸除式裝置), 以便透過這個模組存取
- 您可以為每部輸出裝置定義增益控制 min/max/default/step 值,以毫貝表示 (1 毫貝 = 1/100 dB = 1/1000 bel)。
- devicePort 執行個體上的 address 屬性可用來找出
即使您有多部裝置使用相同的裝置類型
AUDIO_DEVICE_OUT_BUS
。 - MixPorts。包含由公開伺服器公開的所有輸出和輸入串流清單 音訊輸出裝置每個 MixPort 執行個體可視為 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>