Added skip delays when activating user id device affinities
Bug: 269208752
Test: Ran MU workflow observed 90% reduction in audio routing
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:299565553494ad0fbe38d0c737e3140057552fce)
Merged-In: I000369822c82ac38ff7008fafab8bc569bd762a2
Change-Id: I000369822c82ac38ff7008fafab8bc569bd762a2
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 876911d..febccac 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -424,6 +424,15 @@
bool supportsAllDevices(const DeviceVector &devices) const;
/**
+ * @brief supportsAtLeastOne checks if any device in devices is currently supported
+ * @param devices to be checked against
+ * @return true if the device is weakly supported by type (e.g. for non bus / rsubmix devices),
+ * true if the device is supported (both type and address) for bus / remote submix
+ * false otherwise
+ */
+ bool supportsAtLeastOne(const DeviceVector &devices) const;
+
+ /**
* @brief supportsDevicesForPlayback
* @param devices to be checked against
* @return true if the devices is a supported combo for playback
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 92292e1..7e29e10 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -138,7 +138,7 @@
*/
status_t setUserIdDeviceAffinities(int userId, const AudioDeviceTypeAddrVector& devices);
status_t removeUserIdDeviceAffinities(int userId);
- status_t getDevicesForUserId(int userId, Vector<AudioDeviceTypeAddr>& devices) const;
+ status_t getDevicesForUserId(int userId, AudioDeviceTypeAddrVector& devices) const;
void dump(String8 *dst) const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 09ca989..ac1f8b2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -389,6 +389,11 @@
return supportedDevices().containsAllDevices(devices);
}
+bool SwAudioOutputDescriptor::supportsAtLeastOne(const DeviceVector &devices) const
+{
+ return filterSupportedDevices(devices).size() > 0;
+}
+
bool SwAudioOutputDescriptor::supportsDevicesForPlayback(const DeviceVector &devices) const
{
// No considering duplicated output
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 4cfdaad..631fff8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -640,7 +640,7 @@
}
status_t AudioPolicyMixCollection::getDevicesForUserId(int userId,
- Vector<AudioDeviceTypeAddr>& devices) const {
+ AudioDeviceTypeAddrVector& devices) const {
// for each player mix:
// find rules that don't exclude this userId, and add the device to the list
for (size_t i = 0; i < size(); i++) {
@@ -658,7 +658,7 @@
}
}
if (ruleAllowsUserId) {
- devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+ devices.push_back(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
}
}
return NO_ERROR;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 7d667d5..4e758cc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3783,6 +3783,44 @@
return true;
}
+void AudioPolicyManager::changeOutputDevicesMuteState(
+ const AudioDeviceTypeAddrVector& devices) {
+ ALOGVV("%s() num devices %zu", __func__, devices.size());
+
+ std::vector<sp<SwAudioOutputDescriptor>> outputs =
+ getSoftwareOutputsForDevices(devices);
+
+ for (size_t i = 0; i < outputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> outputDesc = outputs[i];
+ DeviceVector prevDevices = outputDesc->devices();
+ checkDeviceMuteStrategies(outputDesc, prevDevices, 0 /* delayMs */);
+ }
+}
+
+std::vector<sp<SwAudioOutputDescriptor>> AudioPolicyManager::getSoftwareOutputsForDevices(
+ const AudioDeviceTypeAddrVector& devices) const
+{
+ std::vector<sp<SwAudioOutputDescriptor>> outputs;
+ DeviceVector deviceDescriptors;
+ for (size_t j = 0; j < devices.size(); j++) {
+ sp<DeviceDescriptor> desc = mHwModules.getDeviceDescriptor(
+ devices[j].mType, devices[j].getAddress(), String8(), AUDIO_FORMAT_DEFAULT);
+ if (desc == nullptr || !audio_is_output_device(devices[j].mType)) {
+ ALOGE("%s: device type %#x address %s not supported or not an output device",
+ __func__, devices[j].mType, devices[j].getAddress());
+ continue;
+ }
+ deviceDescriptors.add(desc);
+ }
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ if (!mOutputs.valueAt(i)->supportsAtLeastOne(deviceDescriptors)) {
+ continue;
+ }
+ outputs.push_back(mOutputs.valueAt(i));
+ }
+ return outputs;
+}
+
status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
const AudioDeviceTypeAddrVector& devices) {
ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
@@ -3849,7 +3887,8 @@
return NO_ERROR;
}
-void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs)
+void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs,
+ bool skipDelays)
{
uint32_t waitMs = 0;
bool wasLeUnicastActive = isLeUnicastActive();
@@ -3875,8 +3914,8 @@
continue;
}
waitMs = setOutputDevices(outputDesc, newDevices, forceRouting, delayMs, nullptr,
- true /*requiresMuteCheck*/,
- !forceRouting /*requiresVolumeCheck*/);
+ !skipDelays /*requiresMuteCheck*/,
+ !forceRouting /*requiresVolumeCheck*/, skipDelays);
// Only apply special touch sound delay once
delayMs = 0;
}
@@ -4061,13 +4100,18 @@
// reevaluate outputs for all devices
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+ changeOutputDevicesMuteState(devices);
+ updateCallAndOutputRouting(false /* forceVolumeReeval */, 0 /* delayMs */,
+ true /* skipDelays */);
+ changeOutputDevicesMuteState(devices);
return NO_ERROR;
}
status_t AudioPolicyManager::removeUserIdDeviceAffinities(int userId) {
ALOGV("%s() userId=%d", __FUNCTION__, userId);
+ AudioDeviceTypeAddrVector devices;
+ mPolicyMixes.getDevicesForUserId(userId, devices);
status_t status = mPolicyMixes.removeUserIdDeviceAffinities(userId);
if (status != NO_ERROR) {
ALOGE("%s() Could not remove all device affinities fo userId = %d",
@@ -4077,7 +4121,10 @@
// reevaluate outputs for all devices
checkForDeviceAndOutputChanges();
- updateCallAndOutputRouting();
+ changeOutputDevicesMuteState(devices);
+ updateCallAndOutputRouting(false /* forceVolumeReeval */, 0 /* delayMs */,
+ true /* skipDelays */);
+ changeOutputDevicesMuteState(devices);
return NO_ERROR;
}
@@ -7324,7 +7371,8 @@
bool force,
int delayMs,
audio_patch_handle_t *patchHandle,
- bool requiresMuteCheck, bool requiresVolumeCheck)
+ bool requiresMuteCheck, bool requiresVolumeCheck,
+ bool skipMuteDelay)
{
// TODO(b/262404095): Consider if the output need to be reopened.
ALOGV("%s device %s delayMs %d", __func__, devices.toString().c_str(), delayMs);
@@ -7332,9 +7380,9 @@
if (outputDesc->isDuplicated()) {
muteWaitMs = setOutputDevices(outputDesc->subOutput1(), devices, force, delayMs,
- nullptr /* patchHandle */, requiresMuteCheck);
+ nullptr /* patchHandle */, requiresMuteCheck, skipMuteDelay);
muteWaitMs += setOutputDevices(outputDesc->subOutput2(), devices, force, delayMs,
- nullptr /* patchHandle */, requiresMuteCheck);
+ nullptr /* patchHandle */, requiresMuteCheck, skipMuteDelay);
return muteWaitMs;
}
@@ -7400,12 +7448,16 @@
// Add half reported latency to delayMs when muteWaitMs is null in order
// to avoid disordered sequence of muting volume and changing devices.
- installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(),
- muteWaitMs == 0 ? (delayMs + (outputDesc->latency() / 2)) : delayMs);
+ int actualDelayMs = !skipMuteDelay && muteWaitMs == 0
+ ? (delayMs + (outputDesc->latency() / 2)) : delayMs;
+ installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), actualDelayMs);
}
- // update stream volumes according to new device
- applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs);
+ // Since the mute is skip, also skip the apply stream volume as that will be applied externally
+ if (!skipMuteDelay) {
+ // update stream volumes according to new device
+ applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs);
+ }
return muteWaitMs;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 98988e7..863c785 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -535,8 +535,9 @@
* and currently active, allow to have proper drain and avoid pops
* @param requiresVolumeCheck true if called requires to reapply volume if the routing did
* not change (but the output is still routed).
+ * @param skipMuteDelay if true will skip mute delay when installing audio patch
* @return the number of ms we have slept to allow new routing to take effect in certain
- * cases.
+ * cases.
*/
uint32_t setOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
const DeviceVector &device,
@@ -544,7 +545,8 @@
int delayMs = 0,
audio_patch_handle_t *patchHandle = NULL,
bool requiresMuteCheck = true,
- bool requiresVolumeCheck = false);
+ bool requiresVolumeCheck = false,
+ bool skipMuteDelay = false);
status_t resetOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_patch_handle_t *patchHandle = NULL);
@@ -647,8 +649,10 @@
/**
* @brief updates routing for all outputs (including call if call in progress).
* @param delayMs delay for unmuting if required
+ * @param skipDelays if true all the delays will be skip while updating routing
*/
- void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
+ void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0,
+ bool skipDelays = false);
bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
return mCallRxSourceClient != nullptr && source == mCallRxSourceClient;
@@ -1241,6 +1245,21 @@
const char* context,
bool matchAddress = true);
+ /**
+ * @brief changeOutputDevicesMuteState mute/unmute devices using checkDeviceMuteStrategies
+ * @param devices devices to mute/unmute
+ */
+ void changeOutputDevicesMuteState(const AudioDeviceTypeAddrVector& devices);
+
+ /**
+ * @brief Returns a vector of software output descriptor that support the queried devices
+ * @param devices devices to query
+ * @param openOutputs open outputs where the devices are supported as determined by
+ * SwAudioOutputDescriptor::supportsAtLeastOne
+ */
+ std::vector<sp<SwAudioOutputDescriptor>> getSoftwareOutputsForDevices(
+ const AudioDeviceTypeAddrVector& devices) const;
+
bool isScoRequestedForComm() const;
bool isHearingAidUsedForComm() const;