通过AudioManager设置Android优先音频输入输出设备

通过AudioManager设置android优先输入输出设备

Android12 之后,AudioManager增加了两个接口,分别用于设置系统优先使用的输入输出音频设备

setPreferredDevicesForStrategy
setPreferredDeviceForCapturePreset

设置优先输出设备

boolean setPreferredDevicesForStrategy(AudioProductStrategy strategy, AudioDeviceInfo device)
{
    AudioDeviceAttributes ada = new AudioDeviceAttributes(device);
    try {
        audioManager.setPreferredDeviceForStrategy(strategy, ada);
        Log.i(TAG, "setPreferredDeviceForStrategy success strategy:" + strategy + " device:" + device);
    } catch (SecurityException e) {
        Log.i(TAG, "setPreferredDeviceForStrategy fail strategy:" + strategy + " device:" + device + ": " + e);
        return false;
    }
    return true;
}

//设置hdmi
void setHdmiOut()
{
    AudioDeviceInfo hdmiout = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_HDMI, 0);
    if (null == hdmiout) {
        Log.i(TAG, "there is no hdmi out device");
        return;
    }
    Log.i(TAG, "setting out device to " + hdmiout);
    setPreferredDevicesForStrategy(getStrageForMedia(), hdmiout);
}
// 设置hdmi与喇叭同时输出
void setHdmiSpeakerOut()
{
    AudioProductStrategy strategy = getStrageForMedia();
    int[] types = {AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, AudioDeviceInfo.TYPE_HDMI};
    List<AudioDeviceAttributes> adas = GetspecifiedOutPutDevices(types);
    try {
        audioManager.setPreferredDevicesForStrategy(strategy, adas);
        Log.i(TAG, "setPreferredDevicesForStrategy success strategy:" + strategy + " device:" + Arrays.toString(types));
    } catch (SecurityException e) {
        Log.i(TAG, "setPreferredDevicesForStrategy fail strategy:" + strategy + " device:" + Arrays.toString(types) + ": " + e);
    }
}

设置输入设备

boolean setPreferredDeviceForCapture(AudioDeviceInfo device)
{
    AudioDeviceAttributes ada = new AudioDeviceAttributes(device);
    try {
        audioManager.setPreferredDeviceForCapturePreset(MediaRecorder.AudioSource.MIC, ada);
        Log.i(TAG, "setPreferredDeviceForCapturePreset success AudioSource: MIC" + " device:" + device);
    } catch (SecurityException e) {
        Log.i(TAG, "setPreferredDeviceForCapturePreset fail AudioSource: MIC" + " device:" + device + ": " + e);
        return false;
    }
    return true;
}

setPreferredDeviceForCapturePreset调用流程如下

setPreferredDevicesForCapturePreset @frameworks/base/services/core/java/com/android/server/audio/AudioService.java
setDevicesRoleForCapturePreset @frameworks/base/media/java/android/media/AudioSystem.java
setDevicesRoleForCapturePreset @frameworks/av/media/libaudioclient/AudioSystem.cpp
setDevicesRoleForCapturePreset @frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
setDevicesRoleForT @frameworks/av/services/audiopolicy/engine/common/src/EngineBase.cpp

android12 版本setDevicesRoleForT只是实现了保存配置,但是录音时候,并没有从配置里面获取,因此需要在录音时候,从配置里面,获取优先选择的设备,需要在frameworks/av目录打以下补丁:

diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 50de0295a1..025ca84d50 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -15,9 +15,9 @@
  */

 #define LOG_TAG "APM::AudioPolicyEngine"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0

-//#define VERY_VERBOSE_LOGGING
+#define VERY_VERBOSE_LOGGING
 #ifdef VERY_VERBOSE_LOGGING
 #define ALOGVV ALOGV
 #else
@@ -654,6 +654,25 @@ audio_devices_t Engine::getPreferredDeviceTypeForLegacyStrategy(
     return AUDIO_DEVICE_NONE;
 }

+DeviceVector Engine::getPreferredAvailableDevicesForAudioSource(
+        const DeviceVector& availableInputDevices, audio_source_t audioSource) const {
+    DeviceVector preferredAvailableDevVec = {};
+    AudioDeviceTypeAddrVector preferredStrategyDevices;
+    const status_t status = getDevicesForRoleAndCapturePreset(
+            audioSource, DEVICE_ROLE_PREFERRED, preferredStrategyDevices);
+    if (status == NO_ERROR) {
+        // there is a preferred device, is it available?
+        preferredAvailableDevVec =
+                availableInputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
+        if (preferredAvailableDevVec.size() > 0) {
+            ALOGVV("%s using pref device %s for audio_source_t %u",
+                   __func__, preferredAvailableDevVec.toString().c_str(), audioSource);
+            return preferredAvailableDevVec;
+        }
+    }
+    return preferredAvailableDevVec;
+}
+
 DeviceVector Engine::getPreferredAvailableDevicesForProductStrategy(
         const DeviceVector& availableOutputDevices, product_strategy_t strategy) const {
     DeviceVector preferredAvailableDevVec = {};
@@ -762,6 +781,14 @@ sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_
         return device;
     }

+    // check if this audio_source_t has a preferred device that is available,
+    // if yes, give priority to it.
+    DeviceVector preferredAvailableDevVec =
+        getPreferredAvailableDevicesForAudioSource(availableInputDevices, attr.source);
+    if (!preferredAvailableDevVec.isEmpty()) {
+        return preferredAvailableDevVec[0];
+    }
+
     device = getDeviceForInputSource(attr.source);
     if (device == nullptr || !audio_is_remote_submix_device(device->type())) {
         // Return immediately if the device is null or it is not a remote submix device.
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 595e289171..d527c5c71c 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -94,6 +94,8 @@ private:
     product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
     audio_devices_t getPreferredDeviceTypeForLegacyStrategy(
         const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const;
+    DeviceVector getPreferredAvailableDevicesForAudioSource(
+            const DeviceVector& availableInputDevices, audio_source_t audioSource) const;
     DeviceVector getPreferredAvailableDevicesForProductStrategy(
         const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;

为了让设置实时更新,还需要打以下补丁

 void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
@@ -3493,6 +3497,8 @@ status_t AudioPolicyManager::setDevicesRoleForCapturePreset(
             "Engine could not set preferred devices %s for audio source %d role %d",
             dumpAudioDeviceTypeAddrVector(devices).c_str(), audioSource, role);

+    if(status == NO_ERROR)
+        checkCloseInputs();
     return status;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值