Add AudioFlinger to PatchPanel thread safety annotations
Test: atest AudioTrackTest AudioRecordTest
Test: atest AAudioTests AudioTrackOffloadTest
Test: atest AudioPlaybackCaptureTest
Test: Camera YouTube
Bug: 275748373
Change-Id: I50aaf6a5fdb3bd9dd9584dd11c6e1ab5b3a1d540
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 63ce7c4..0ba105f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -4667,7 +4667,7 @@
struct audio_port* ports) const
{
audio_utils::lock_guard _l(mutex());
- return mPatchPanel->listAudioPorts(num_ports, ports);
+ return mPatchPanel->listAudioPorts_l(num_ports, ports);
}
/* Get supported attributes for a given audio port */
@@ -4678,7 +4678,7 @@
}
audio_utils::lock_guard _l(mutex());
- return mPatchPanel->getAudioPort(port);
+ return mPatchPanel->getAudioPort_l(port);
}
/* Connect a patch between several source and sink ports */
@@ -4691,14 +4691,14 @@
}
audio_utils::lock_guard _l(mutex());
- return mPatchPanel->createAudioPatch(patch, handle);
+ return mPatchPanel->createAudioPatch_l(patch, handle);
}
/* Disconnect a patch */
status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
{
audio_utils::lock_guard _l(mutex());
- return mPatchPanel->releaseAudioPatch(handle);
+ return mPatchPanel->releaseAudioPatch_l(handle);
}
/* List connected audio ports and they attributes */
@@ -4706,7 +4706,7 @@
unsigned int* num_patches, struct audio_patch* patches) const
{
audio_utils::lock_guard _l(mutex());
- return mPatchPanel->listAudioPatches(num_patches, patches);
+ return mPatchPanel->listAudioPatches_l(num_patches, patches);
}
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
index 9302e25..5a6621e 100644
--- a/services/audioflinger/IAfPatchPanel.h
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -45,8 +45,7 @@
mRecordThreadHandle(recordThreadHandle) {}
SoftwarePatch(const SoftwarePatch&) = default;
- // Must be called under AudioFlinger::mLock
- status_t getLatencyMs_l(double* latencyMs) const;
+ status_t getLatencyMs_l(double* latencyMs) const REQUIRES(audio_utils::AudioFlinger_Mutex);
audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
@@ -60,12 +59,14 @@
class IAfPatchPanelCallback : public virtual RefBase {
public:
- virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) = 0;
- virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) = 0;
- virtual IAfPlaybackThread* primaryPlaybackThread_l() const = 0;
- virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const = 0;
- virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const = 0;
- virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const = 0;
+ virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) REQUIRES(mutex()) = 0;
+ virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) REQUIRES(mutex()) = 0;
+ virtual IAfPlaybackThread* primaryPlaybackThread_l() const REQUIRES(mutex()) = 0;
+ virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const
+ REQUIRES(mutex()) = 0;
+ virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const
+ REQUIRES(mutex()) = 0;
+ virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const REQUIRES(mutex()) = 0;
virtual sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
audio_io_handle_t* input,
audio_config_t* config,
@@ -74,22 +75,25 @@
audio_source_t source,
audio_input_flags_t flags,
audio_devices_t outputDevice,
- const String8& outputDeviceAddress) = 0;
+ const String8& outputDeviceAddress) REQUIRES(mutex()) = 0;
virtual sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
audio_io_handle_t* output,
audio_config_t* halConfig,
audio_config_base_t* mixerConfig,
audio_devices_t deviceType,
const String8& address,
- audio_output_flags_t flags) = 0;
- virtual audio_utils::mutex& mutex() const = 0;
+ audio_output_flags_t flags) REQUIRES(mutex()) = 0;
+ virtual audio_utils::mutex& mutex() const
+ RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
- getAudioHwDevs_l() const = 0;
+ getAudioHwDevs_l() const REQUIRES(mutex()) = 0;
virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
virtual void updateDownStreamPatches_l(
- const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams) = 0;
- virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) = 0;
+ const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams)
+ REQUIRES(mutex()) = 0;
+ virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices)
+ REQUIRES(mutex()) = 0;
};
class IAfPatchPanel : public virtual RefBase {
@@ -133,9 +137,12 @@
sp<const ThreadType> const_thread() const { return mThread; }
sp<const TrackType> const_track() const { return mTrack; }
- void closeConnections(const sp<IAfPatchPanel>& panel) {
+ void closeConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex)
+ NO_THREAD_SAFETY_ANALYSIS // this is broken in clang
+ {
if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
- panel->releaseAudioPatch(mHandle);
+ panel->releaseAudioPatch_l(mHandle);
mHandle = AUDIO_PATCH_HANDLE_NONE;
}
if (mThread != nullptr) {
@@ -217,8 +224,10 @@
friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); }
- status_t createConnections(const sp<IAfPatchPanel>& panel);
- void clearConnections(const sp<IAfPatchPanel>& panel);
+ status_t createConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void clearConnections_l(const sp<IAfPatchPanel>& panel)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
bool isSoftware() const {
return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE;
@@ -250,22 +259,27 @@
};
/* List connected audio ports and their attributes */
- virtual status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) = 0;
+ virtual status_t listAudioPorts_l(unsigned int* num_ports, struct audio_port* ports)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* Get supported attributes for a given audio port */
- virtual status_t getAudioPort(struct audio_port_v7* port) = 0;
+ virtual status_t getAudioPort_l(struct audio_port_v7* port)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* Create a patch between several source and sink ports */
- virtual status_t createAudioPatch(
+ virtual status_t createAudioPatch_l(
const struct audio_patch* patch,
audio_patch_handle_t* handle,
- bool endpointPatch = false) = 0;
+ bool endpointPatch = false)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* Release a patch */
- virtual status_t releaseAudioPatch(audio_patch_handle_t handle) = 0;
+ virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
/* List connected audio devices and they attributes */
- virtual status_t listAudioPatches(unsigned int* num_patches, struct audio_patch* patches) = 0;
+ virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches)
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
// Retrieves all currently estrablished software patches for a stream
// opened on an intermediate module.
@@ -280,13 +294,14 @@
virtual void dump(int fd) const = 0;
- // Must be called under AudioFlinger::mLock
+ virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const = 0;
+ virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
- virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const = 0;
-
- virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const = 0;
+ virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
+ REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
};
} // namespace android
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 49a0e9b..89f0a6e 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -83,7 +83,7 @@
}
/* List connected audio ports and their attributes */
-status_t PatchPanel::listAudioPorts(unsigned int* /* num_ports */,
+status_t PatchPanel::listAudioPorts_l(unsigned int* /* num_ports */,
struct audio_port *ports __unused)
{
ALOGV(__func__);
@@ -91,14 +91,14 @@
}
/* Get supported attributes for a given audio port */
-status_t PatchPanel::getAudioPort(struct audio_port_v7* port)
+status_t PatchPanel::getAudioPort_l(struct audio_port_v7* port)
{
if (port->type != AUDIO_PORT_TYPE_DEVICE) {
// Only query the HAL when the port is a device.
// TODO: implement getAudioPort for mix.
return INVALID_OPERATION;
}
- AudioHwDevice* hwDevice = findAudioHwDeviceByModule(port->ext.device.hw_module);
+ AudioHwDevice* hwDevice = findAudioHwDeviceByModule_l(port->ext.device.hw_module);
if (hwDevice == nullptr) {
ALOGW("%s cannot find hw module %d", __func__, port->ext.device.hw_module);
return BAD_VALUE;
@@ -110,7 +110,7 @@
}
/* Connect a patch between several source and sink ports */
-status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
+status_t PatchPanel::createAudioPatch_l(const struct audio_patch* patch,
audio_patch_handle_t *handle,
bool endpointPatch)
//unlocks AudioFlinger::mLock when calling IAfThreadBase::sendCreateAudioPatchConfigEvent
@@ -145,7 +145,7 @@
// 1) if a software patch is present, release the playback and capture threads and
// tracks created. This will also release the corresponding audio HAL patches
if (removedPatch.isSoftware()) {
- removedPatch.clearConnections(this);
+ removedPatch.clearConnections_l(this);
}
// 2) if the new patch and old patch source or sink are devices from different
// hw modules, clear the audio HAL patches now because they will not be updated
@@ -171,7 +171,7 @@
// removedPatch.mHalHandle would be AUDIO_PATCH_HANDLE_NONE in this case.
hwModule = oldPatch.sinks[0].ext.device.hw_module;
}
- sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(hwModule);
+ sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(hwModule);
if (hwDevice != 0) {
hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
}
@@ -191,7 +191,7 @@
switch (patch->sources[0].type) {
case AUDIO_PORT_TYPE_DEVICE: {
audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module;
- AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(srcModule);
+ AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(srcModule);
if (!audioHwDevice) {
status = BAD_VALUE;
goto exit;
@@ -323,7 +323,7 @@
goto exit;
}
newPatch.mRecord.setThread(thread->asIAfRecordThread().get());
- status = newPatch.createConnections(this);
+ status = newPatch.createConnections_l(this);
if (status != NO_ERROR) {
goto exit;
}
@@ -449,11 +449,11 @@
mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(*handle, newPatch);
}
if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
- addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
+ addSoftwarePatchToInsertedModules_l(insertedModule, *handle, &newPatch.mAudioPatch);
}
mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
} else {
- newPatch.clearConnections(this);
+ newPatch.clearConnections_l(this);
}
return status;
}
@@ -464,10 +464,10 @@
mRecord.handle(), mPlayback.handle());
}
-status_t PatchPanel::Patch::createConnections(const sp<IAfPatchPanel>& panel)
+status_t PatchPanel::Patch::createConnections_l(const sp<IAfPatchPanel>& panel)
{
// create patch from source device to record thread input
- status_t status = panel->createAudioPatch(
+ status_t status = panel->createAudioPatch_l(
PatchBuilder().addSource(mAudioPatch.sources[0]).
addSink(mRecord.thread(), { .source = AUDIO_SOURCE_MIC }).patch(),
mRecord.handlePtr(),
@@ -479,7 +479,7 @@
// create patch from playback thread output to sink device
if (mAudioPatch.num_sinks != 0) {
- status = panel->createAudioPatch(
+ status = panel->createAudioPatch_l(
PatchBuilder().addSource(mPlayback.thread()).addSink(mAudioPatch.sinks[0]).patch(),
mPlayback.handlePtr(),
true /*endpointPatch*/);
@@ -628,15 +628,15 @@
return status;
}
-void PatchPanel::Patch::clearConnections(const sp<IAfPatchPanel>& panel)
+void PatchPanel::Patch::clearConnections_l(const sp<IAfPatchPanel>& panel)
{
ALOGV("%s() mRecord.handle %d mPlayback.handle %d",
__func__, mRecord.handle(), mPlayback.handle());
mRecord.stopTrack();
mPlayback.stopTrack();
mRecord.clearTrackPeer(); // mRecord stop is synchronous. Break PeerProxy sp<> cycle.
- mRecord.closeConnections(panel);
- mPlayback.closeConnections(panel);
+ mRecord.closeConnections_l(panel);
+ mPlayback.closeConnections_l(panel);
}
status_t PatchPanel::Patch::getLatencyMs(double* latencyMs) const
@@ -726,7 +726,7 @@
}
/* Disconnect a patch */
-status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
+status_t PatchPanel::releaseAudioPatch_l(audio_patch_handle_t handle)
//unlocks AudioFlinger::mLock when calling IAfThreadBase::sendReleaseAudioPatchConfigEvent
//to avoid deadlocks if the thread loop needs to acquire AudioFlinger::mLock
//before processing the release patch request.
@@ -745,7 +745,7 @@
const struct audio_port_config &src = patch.sources[0];
switch (src.type) {
case AUDIO_PORT_TYPE_DEVICE: {
- sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(src.ext.device.hw_module);
+ sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(src.ext.device.hw_module);
if (hwDevice == 0) {
ALOGW("%s() bad src hw module %d", __func__, src.ext.device.hw_module);
status = BAD_VALUE;
@@ -753,7 +753,7 @@
}
if (removedPatch.isSoftware()) {
- removedPatch.clearConnections(this);
+ removedPatch.clearConnections_l(this);
break;
}
@@ -776,7 +776,7 @@
}
} break;
case AUDIO_PORT_TYPE_MIX: {
- if (findHwDeviceByModule(src.ext.mix.hw_module) == 0) {
+ if (findHwDeviceByModule_l(src.ext.mix.hw_module) == 0) {
ALOGW("%s() bad src hw module %d", __func__, src.ext.mix.hw_module);
status = BAD_VALUE;
break;
@@ -812,7 +812,7 @@
}
/* List connected audio ports and they attributes */
-status_t PatchPanel::listAudioPatches(unsigned int* /* num_patches */,
+status_t PatchPanel::listAudioPatches_l(unsigned int* /* num_patches */,
struct audio_patch *patches __unused)
{
ALOGV(__func__);
@@ -869,7 +869,7 @@
}
}
-AudioHwDevice* PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
+AudioHwDevice* PatchPanel::findAudioHwDeviceByModule_l(audio_module_handle_t module)
{
if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(module);
@@ -880,13 +880,13 @@
return mAfPatchPanelCallback->getAudioHwDevs_l().valueAt(index);
}
-sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
+sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule_l(audio_module_handle_t module)
{
- AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(module);
+ AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(module);
return audioHwDevice ? audioHwDevice->hwDevice() : nullptr;
}
-void PatchPanel::addSoftwarePatchToInsertedModules(
+void PatchPanel::addSoftwarePatchToInsertedModules_l(
audio_module_handle_t module, audio_patch_handle_t handle,
const struct audio_patch *patch)
{
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index a95c601..cec554c 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -30,25 +30,29 @@
: mAfPatchPanelCallback(afPatchPanelCallback) {}
/* List connected audio ports and their attributes */
- status_t listAudioPorts(unsigned int *num_ports,
- struct audio_port* ports) final;
+ status_t listAudioPorts_l(unsigned int *num_ports,
+ struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Get supported attributes for a given audio port */
- status_t getAudioPort(struct audio_port_v7* port) final;
+ status_t getAudioPort_l(struct audio_port_v7* port) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Create a patch between several source and sink ports */
- status_t createAudioPatch(const struct audio_patch *patch,
+ status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle,
- bool endpointPatch = false) final;
+ bool endpointPatch = false) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* Release a patch */
- status_t releaseAudioPatch(audio_patch_handle_t handle) final;
+ status_t releaseAudioPatch_l(audio_patch_handle_t handle) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
/* List connected audio devices and they attributes */
- status_t listAudioPatches(unsigned int *num_patches,
- struct audio_patch* patches) final;
+ status_t listAudioPatches_l(unsigned int *num_patches,
+ struct audio_patch* patches) final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- // Retrieves all currently estrablished software patches for a stream
+ // Retrieves all currently established software patches for a stream
// opened on an intermediate module.
status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
std::vector<SoftwarePatch>* patches) const final;
@@ -60,20 +64,24 @@
void dump(int fd) const final;
- // Call with AudioFlinger mLock held
- const std::map<audio_patch_handle_t, Patch>& patches_l() const final { return mPatches; }
+ const std::map<audio_patch_handle_t, Patch>& patches_l() const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; }
- // Must be called under AudioFlinger::mLock
- status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final;
+ status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
- void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final;
+ void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
private:
- AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
- sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
- void addSoftwarePatchToInsertedModules(
+ AudioHwDevice* findAudioHwDeviceByModule_l(audio_module_handle_t module)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ sp<DeviceHalInterface> findHwDeviceByModule_l(audio_module_handle_t module)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
+ void addSoftwarePatchToInsertedModules_l(
audio_module_handle_t module, audio_patch_handle_t handle,
- const struct audio_patch *patch);
+ const struct audio_patch *patch)
+ REQUIRES(audio_utils::AudioFlinger_Mutex);
void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
/**
* erase the patch referred by its handle.