在 AAOS 中連接輸入裝置

您可以使用下列機制在 Android 中播放音訊:

每種機制都允許在 Android 中播放音訊。如果是播放電台或輸入裝置的音訊,這些選項可能不夠用,但每個選項都可以搭配音訊擷取或 MediaRecorder 類別,先擷取音訊,然後從 Android 播放。特別是系統應用程式,可使用下列資訊將輸入裝置連線至 AAOS 中的輸出混音器。

HwAudioSource 播放器

HwAudioSource 將音訊來源裝置直接連線至 Android 混音器。

動機

使用裝置對裝置或硬體音訊修補程式搭配 Android 時,可能會遇到一些限制。每個選項都無法接收媒體按鍵事件,例如 PLAYPAUSESTOP,而且由於這些選項會規避 Android 的音訊堆疊,因此每個選項都需要硬體將修補程式混入 Android 的其他音訊。

使用 HwAudioSource

HwAudioSource 是一種新型播放器,設計為軟體修補程式。這樣一來,使用這個播放器的應用程式就能接收媒體按鍵事件,而 Android 則可混合及轉送輸出串流。

mHwAudioSource = new HwAudioSource.Builder()
                .setAudioDeviceInfo(AudioDeviceInfo: info)
                .setAudioAttributes(new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .build())
                .build();
mHwAudioSource.play();
mHwAudioSource.stop();

音訊 HAL 的變更

使用這個新播放器時,請注意音訊 HAL 的這些預期行為。例如:device/generic/car/emulator/audio/driver/audio_hw.c

  • adev_create_audio_patch 預期要求從裝置到混音器建立音訊修補程式。

  • adev_open_input_stream 預期 audio_sourceAUDIO_SOURCE_FM_TUNER

  • in_read 會在音訊緩衝區中填入廣播電台音訊資料。

建議您在 audio_policy_configuration.xml 中設定型別為 AUDIO_DEVICE_IN_FM_TUNER 的調諧器裝置:

<devicePort
    tagName="Tuner_source"
    type="AUDIO_DEVICE_IN_FM_TUNER"
    role="source"
    address="tuner0">
    <profile
        name=""
        format="AUDIO_FORMAT_PCM_16_BIT"
        samplingRates="48000"
        channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</devicePort>

透過這項裝置設定,您可以使用 AudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS 搭配 AudioDeviceInfo.TYPE_FM_TUNER,輕鬆找到 FM 收音機輸入裝置。

建立音訊修補程式

您可以在兩個音訊連接埠之間建立音訊修補程式,可以是混音連接埠或裝置連接埠。一般來說,從混音埠到裝置埠的音訊修補程式用於播放,反向則用於擷取。

舉例來說,如果音訊修補程式將音訊樣本從 FM_TUNER 來源直接傳送至媒體接收器,就會略過軟體混音器。然後,您必須使用硬體混音器,混合 Android 和 FM_TUNER 的音訊樣本,以供接收器使用。直接從 FM_TUNER 來源建立音訊修補程式至媒體接收器時:

  • 音量控制適用於媒體接收器,應會影響 Android 和 FM_TUNER 音訊。

  • 使用者只要切換應用程式,即可在 Android 和 FM_TUNER 音訊之間切換 (無需明確選擇媒體來源)。

汽車實作項目可能也需要在兩個裝置連接埠之間建立音訊修補程式。如要這麼做,您必須先在 audio_policy_configuration.xml 中宣告裝置通訊埠和可能的路徑,然後將 mixport 與裝置通訊埠建立關聯。

範例設定

請參閱這個設定範例:device/generic/car/emulator/audio/audio_policy_configuration.xml

<audioPolicyConfiguration>
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>bus0_media_out</item>
                <item>bus1_audio_patch_test_in</item>
            </attachedDevices>
            <mixPorts>
                <mixPort name="mixport_bus0_media_out" role="source"
                        flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
                <mixPort name="mixport_audio_patch_in" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                           samplingRates="48000"
                           channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
                        address="bus0_media_out">
                    <profile balance="" 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>
                <devicePort tagName="bus1_audio_patch_test_in" type="AUDIO_DEVICE_IN_BUS" role="source"
                        address="bus1_audio_patch_test_in">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_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_media_out" sources="mixport_bus0_media_out,bus1_audio_patch_test_in"/>
                <route type="mix" sink="mixport_audio_patch_in" sources="bus1_audio_patch_test_in"/>
            </routes>
        </module>
    </modules>
</audioPolicyConfiguration>

音訊驅動程式 API

您可以使用 getExternalSources() 擷取可用來源清單 (依地址識別),然後依音訊用途在這些來源和接收器通訊埠之間建立音訊修補程式。音訊 HAL 上的對應進入點會顯示在 IDevice.hal 中:

Interface IDevice {
...
/
*   Creates an audio patch between several source and sink ports.  The handle
*   is allocated by the HAL and must be unique for this audio HAL module.
*
*   @param sources patch sources.
*   @param sinks patch sinks.
*   @return retval operation completion status.
*   @return patch created patch handle.
*/
createAudioPatch(vec<AudioPortConfig> sources, vec<AudioPortConfig> sinks)
       generates (Result retval, AudioPatchHandle patch);

*   Release an audio patch.
*
*   @param patch patch handle.
*   @return retval operation completion status.
*/
releaseAudioPatch(AudioPatchHandle patch) generates (Result retval);
...
}

電台

建構電台應用程式時,建議您使用 HwAudioSource,因為這個類別會建立修補程式和媒體工作階段,以處理媒體金鑰事件。您可以為同一個來源和音訊屬性建立多個音訊來源。你可以設定一個用於一般電台使用,另一個用於交通資訊公告。

如果錄製 FM_TUNER,Android 11 已將相關權限變更為 android.permission.CAPTURE_AUDIO_OUTPUT。不再需要通過 OP_RECORD_AUDIO 權限檢查 (僅適用於麥克風)。由於 FM_TUNER 存取權已SYSTEM_API要求權限,因此這項異動對應用程式應不會造成影響。

如要進一步瞭解如何建構電台應用程式,請參閱「實作電台」。