APM: Coalesce calls to check and update outputs
Introduce a method 'checkForDeviceAndOutputChanges' that calls
'check...' and 'update...' methods in the correct sequence.
Bug: 63901775
Test: make
Change-Id: I32fc39d5b62a29e9c1801cb89046fad6fa156073
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 687dd60..9409023 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -202,27 +202,25 @@
return BAD_VALUE;
}
- // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP
- // output is suspended before any tracks are moved to it
- checkA2dpSuspend();
- checkOutputForAllStrategies();
- // outputs must be closed after checkOutputForAllStrategies() is executed
- if (!outputs.isEmpty()) {
- for (audio_io_handle_t output : outputs) {
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
- // close unused outputs after device disconnection or direct outputs that have been
- // opened by checkOutputsForDevice() to query dynamic parameters
- if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
- (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
- (desc->mDirectOpenCount == 0))) {
- closeOutput(output);
+ checkForDeviceAndOutputChanges([&]() {
+ // outputs must be closed after checkOutputForAllStrategies() is executed
+ if (!outputs.isEmpty()) {
+ for (audio_io_handle_t output : outputs) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
+ // close unused outputs after device disconnection or direct outputs that have been
+ // opened by checkOutputsForDevice() to query dynamic parameters
+ if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
+ (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
+ (desc->mDirectOpenCount == 0))) {
+ closeOutput(output);
+ }
}
+ // check A2DP again after closing A2DP output to reset mA2dpSuspended if needed
+ return true;
}
- // check again after closing A2DP output to reset mA2dpSuspended if needed
- checkA2dpSuspend();
- }
+ return false;
+ });
- updateDevicesAndOutputs();
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
updateCallRouting(newDevice);
@@ -565,9 +563,7 @@
|| (is_state_in_call(state) && (state != oldState)));
// check for device and output changes triggered by new phone state
- checkA2dpSuspend();
- checkOutputForAllStrategies();
- updateDevicesAndOutputs();
+ checkForDeviceAndOutputChanges();
int delayMs = 0;
if (isStateInCall(state)) {
@@ -667,9 +663,7 @@
(usage == AUDIO_POLICY_FORCE_FOR_SYSTEM);
// check for device and output changes triggered by new force usage
- checkA2dpSuspend();
- checkOutputForAllStrategies();
- updateDevicesAndOutputs();
+ checkForDeviceAndOutputChanges();
//FIXME: workaround for truncated touch sounds
// to be removed when the problem is handled by system UI
@@ -4631,6 +4625,21 @@
return true;
}
+void AudioPolicyManager::checkForDeviceAndOutputChanges()
+{
+ checkForDeviceAndOutputChanges([](){ return false; });
+}
+
+void AudioPolicyManager::checkForDeviceAndOutputChanges(std::function<bool()> onOutputsChecked)
+{
+ // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP
+ // output is suspended before any tracks are moved to it
+ checkA2dpSuspend();
+ checkOutputForAllStrategies();
+ if (onOutputsChecked()) checkA2dpSuspend();
+ updateDevicesAndOutputs();
+}
+
void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
{
audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 136e522..3010989 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -17,6 +17,7 @@
#pragma once
#include <atomic>
+#include <functional>
#include <memory>
#include <unordered_set>
@@ -406,6 +407,13 @@
// close an input.
void closeInput(audio_io_handle_t input);
+ // runs all the checks required for accomodating changes in devices and outputs
+ // if 'onOutputsChecked' callback is provided, it is executed after the outputs
+ // check via 'checkOutputForAllStrategies'. If the callback returns 'true',
+ // A2DP suspend status is rechecked.
+ void checkForDeviceAndOutputChanges();
+ void checkForDeviceAndOutputChanges(std::function<bool()> onOutputsChecked);
+
// checks and if necessary changes outputs used for all strategies.
// must be called every time a condition that affects the output choice for a given strategy
// changes: connected device, phone state, force use...