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

Commit 7cd766aa authored by Andy Hung's avatar Andy Hung Committed by Gerrit Code Review
Browse files

Merge "Add AudioFlinger to PatchPanel thread safety annotations" into main

parents 722c9c91 36346128
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);