通过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;
}