[BUG] AudioPolicy: fix AudioDeviceCallback
This CL fixes the AudioDeviceCallback that may report null device.
When an output is reused by a SwBridge, upon release of SW bridge patch,
releasing the patch of the Playback PatchTrack associated with the mixer thread
will clear its patch and output devices.
As the patch created for this output may not be recreated by AudioPolicyManager
if routing does not change (same device or none if no activity on output),
the device will not be updated, hence the AudioDeviceCallback will report null
device.
AudioPolicy will now force to recreate the output patch with same
handle and valid when the SwBridge is released.
AudioFlinger will erase previous mixer output patch and reuse
hal patch handle to recreate/update the hal audio patch.
Test: run a SwBridge audio use case on primary output (e.g. FM Radio),
stop it, then play a stream on primary output.
Ensure AudioDeviceCallback is called with non null device.
Signed-off-by: Francois Gaffie <francois.gaffie@renault.com>
Change-Id: I0b4f852280046cc596da9194cab4655316a026a4
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 4a62eda..8a3cd63 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4539,7 +4539,8 @@
ALOGE("%s output is duplicated", __func__);
return INVALID_OPERATION;
}
- sourceDesc->setSwOutput(outputDesc);
+ bool closeOutput = outputDesc->mDirectOpenCount != 0;
+ sourceDesc->setSwOutput(outputDesc, closeOutput);
} else {
// Same for "raw patches" aka created from createAudioPatch API
SortedVector<audio_io_handle_t> outputs =
@@ -4558,7 +4559,7 @@
__func__, sinkDevice->toString().c_str());
return INVALID_OPERATION;
}
- sourceDesc->setSwOutput(outputDesc);
+ sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false);
}
// create a software bridge in PatchPanel if:
// - source and sink devices are on different HW modules OR
@@ -4687,17 +4688,29 @@
// releaseOutput has already called closeOutput in case of direct output
return NO_ERROR;
}
- if (!outputDesc->isActive() && !sourceDesc->useSwBridge()) {
- resetOutputDevice(outputDesc);
- } else {
- // Reuse patch handle if still valid / do not force rerouting if still routed
- patchHandle = outputDesc->getPatchHandle();
- setOutputDevices(outputDesc,
- getNewOutputDevices(outputDesc, true /*fromCache*/),
- patchHandle == AUDIO_PATCH_HANDLE_NONE, /*force*/
- 0,
- patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle);
- }
+ patchHandle = outputDesc->getPatchHandle();
+ // When a Sw bridge is released, the mixer used by this bridge will release its
+ // patch at AudioFlinger side. Hence, the mixer audio patch must be recreated
+ // Reuse patch handle to force audio flinger removing initial mixer patch removal
+ // updating hal patch handle (prevent leaks).
+ // While using a HwBridge, force reconsidering device only if not reusing an existing
+ // output and no more activity on output (will force to close).
+ bool force = sourceDesc->useSwBridge() ||
+ (sourceDesc->canCloseOutput() && !outputDesc->isActive());
+ // APM pattern is to have always outputs opened / patch realized for reachable devices.
+ // Update device may result to NONE (empty), coupled with force, it releases the patch.
+ // Reconsider device only for cases:
+ // 1 / Active Output
+ // 2 / Inactive Output previously hosting HwBridge
+ // 3 / Inactive Output previously hosting SwBridge that can be closed.
+ bool updateDevice = outputDesc->isActive() || !sourceDesc->useSwBridge() ||
+ sourceDesc->canCloseOutput();
+ setOutputDevices(outputDesc,
+ updateDevice ? getNewOutputDevices(outputDesc, true /*fromCache*/) :
+ outputDesc->devices(),
+ force,
+ 0,
+ patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle);
} else {
return BAD_VALUE;
}