Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36346128 authored by Andy Hung's avatar Andy Hung
Browse files

Add AudioFlinger to PatchPanel thread safety annotations

Test: atest AudioTrackTest AudioRecordTest
Test: atest AAudioTests AudioTrackOffloadTest
Test: atest AudioPlaybackCaptureTest
Test: Camera YouTube
Bug: 275748373
Merged-In: I50aaf6a5fdb3bd9dd9584dd11c6e1ab5b3a1d540
Change-Id: I50aaf6a5fdb3bd9dd9584dd11c6e1ab5b3a1d540
parent 51c7a1e9
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -4563,7 +4563,7 @@ status_t AudioFlinger::listAudioPorts(unsigned int* num_ports,
        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 */
@@ -4574,7 +4574,7 @@ status_t AudioFlinger::getAudioPort(struct audio_port_v7* port) const {
    }

    audio_utils::lock_guard _l(mutex());
    return mPatchPanel->getAudioPort(port);
    return mPatchPanel->getAudioPort_l(port);
}

/* Connect a patch between several source and sink ports */
@@ -4587,14 +4587,14 @@ status_t AudioFlinger::createAudioPatch(
    }

    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 */
@@ -4602,7 +4602,7 @@ status_t AudioFlinger::listAudioPatches(
        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);
}

// ----------------------------------------------------------------------------
+44 −29
Original line number Diff line number Diff line
@@ -45,8 +45,7 @@ public:
          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 @@ private:

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 @@ public:
            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 @@ public:
        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 @@ public:

        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 @@ public:
    };

    /* 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 @@ public:

    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
+25 −25
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ void PatchPanel::closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
}

/* 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 @@ status_t PatchPanel::listAudioPorts(unsigned int* /* num_ports */,
}

/* 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 @@ status_t PatchPanel::getAudioPort(struct audio_port_v7* port)
}

/* 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
@@ -144,7 +144,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
            // 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
@@ -169,7 +169,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                    // 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);
                }
@@ -185,7 +185,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
    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;
@@ -317,7 +317,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                    goto exit;
                }
                newPatch.mRecord.setThread(thread->asIAfRecordThread().get());
                status = newPatch.createConnections(this);
                status = newPatch.createConnections_l(this);
                if (status != NO_ERROR) {
                    goto exit;
                }
@@ -438,11 +438,11 @@ exit:
        newPatch.mHalHandle = halHandle;
        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;
}
@@ -453,10 +453,10 @@ PatchPanel::Patch::~Patch()
            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(),
@@ -468,7 +468,7 @@ status_t PatchPanel::Patch::createConnections(const sp<IAfPatchPanel>& panel)

    // 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*/);
@@ -617,15 +617,15 @@ status_t PatchPanel::Patch::createConnections(const sp<IAfPatchPanel>& panel)
    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
@@ -715,7 +715,7 @@ String8 PatchPanel::Patch::dump(audio_patch_handle_t myHandle) const
}

/* 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.
@@ -734,7 +734,7 @@ status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
    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;
@@ -742,7 +742,7 @@ status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
            }

            if (removedPatch.isSoftware()) {
                removedPatch.clearConnections(this);
                removedPatch.clearConnections_l(this);
                break;
            }

@@ -765,7 +765,7 @@ status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
            }
        } 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;
@@ -799,7 +799,7 @@ void PatchPanel::erasePatch(audio_patch_handle_t handle) {
}

/* 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__);
@@ -856,7 +856,7 @@ void PatchPanel::notifyStreamClosed(audio_io_handle_t stream)
    }
}

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);
@@ -867,13 +867,13 @@ AudioHwDevice* PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t modul
    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)
{
+26 −18
Original line number Diff line number Diff line
@@ -30,25 +30,29 @@ public:
        : 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 @@ public:

    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);
    void erasePatch(audio_patch_handle_t handle);