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

Commit 35ea409b authored by Vlad Popa's avatar Vlad Popa Committed by Android (Google) Code Review
Browse files

Merge "Refactor the PatchCommandThread for reuse."

parents c9f2938e 5161f8aa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ cc_library_shared {
        "FastThreadDumpState.cpp",
        "FastThreadState.cpp",
        "NBAIO_Tee.cpp",
        "PatchCommandThread.cpp",
        "PatchPanel.cpp",
        "PropertyUtils.cpp",
        "SpdifStreamOut.cpp",
+4 −3
Original line number Diff line number Diff line
@@ -323,7 +323,8 @@ AudioFlinger::AudioFlinger()
      mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
      mGlobalEffectEnableTime(0),
      mPatchPanel(this),
      mDeviceEffectManager(this),
      mPatchCommandThread(sp<PatchCommandThread>::make()),
      mDeviceEffectManager(sp<DeviceEffectManager>::make(*this)),
      mSystemReady(false)
{
    // Move the audio session unique ID generator start base as time passes to limit risk of
@@ -873,7 +874,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)

        mPatchPanel.dump(fd);

        mDeviceEffectManager.dump(fd);
        mDeviceEffectManager->dump(fd);

        // dump external setParameters
        auto dumpLogger = [fd](SimpleLog& logger, const char* name) {
@@ -4069,7 +4070,7 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request,
        if (sessionId == AUDIO_SESSION_DEVICE) {
            sp<Client> client = registerPid(currentPid);
            ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress());
            handle = mDeviceEffectManager.createEffect_l(
            handle = mDeviceEffectManager->createEffect_l(
                    &descOut, device, client, effectClient, mPatchPanel.patches_l(),
                    &enabledOut, &lStatus, probe, request.notifyFramesProcessed);
            if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+4 −1
Original line number Diff line number Diff line
@@ -634,6 +634,8 @@ using effect_buffer_t = int16_t;

#include "Effects.h"

#include "PatchCommandThread.h"

#include "DeviceEffectManager.h"

    // Find io handle by session id.
@@ -1012,7 +1014,8 @@ private:
    PatchPanel mPatchPanel;
    sp<EffectsFactoryHalInterface> mEffectsFactoryHal;

    DeviceEffectManager mDeviceEffectManager;
    const sp<PatchCommandThread> mPatchCommandThread;
    sp<DeviceEffectManager> mDeviceEffectManager;

    bool       mSystemReady;
    std::atomic_bool mAudioPolicyReady{};
+1 −103
Original line number Diff line number Diff line
@@ -32,16 +32,6 @@ namespace android {

using media::IEffectClient;

void AudioFlinger::DeviceEffectManager::createAudioPatch(audio_patch_handle_t handle,
        const PatchPanel::Patch& patch) {
    ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
            __func__, handle, patch.mHalHandle,
            patch.mAudioPatch.num_sinks,
            patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);

    mCommandThread->createAudioPatchCommand(handle, patch);
}

void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
        const PatchPanel::Patch& patch) {
    ALOGV("%s handle %d mHalHandle %d device sink %08x",
@@ -55,11 +45,6 @@ void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t
    }
}

void AudioFlinger::DeviceEffectManager::releaseAudioPatch(audio_patch_handle_t handle) {
    ALOGV("%s", __func__);
    mCommandThread->releaseAudioPatchCommand(handle);
}

void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
    ALOGV("%s", __func__);
    Mutex::Autolock _l(mLock);
@@ -116,7 +101,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l
            }
        }
    }
    if (enabled != NULL) {
    if (enabled != nullptr) {
        *enabled = (int)effect->isEnabled();
    }
    *status = lStatus;
@@ -208,91 +193,4 @@ bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
    return true;
}

// -----------  DeviceEffectManager::CommandThread implementation ----------


AudioFlinger::DeviceEffectManager::CommandThread::~CommandThread()
{
    Mutex::Autolock _l(mLock);
    mCommands.clear();
}

void AudioFlinger::DeviceEffectManager::CommandThread::onFirstRef()
{
    run("DeviceEffectManage_CommandThread", ANDROID_PRIORITY_AUDIO);
}

bool AudioFlinger::DeviceEffectManager::CommandThread::threadLoop()
{
    mLock.lock();
    while (!exitPending())
    {
        while (!mCommands.empty() && !exitPending()) {
            sp<Command> command = mCommands.front();
            mCommands.pop_front();
            mLock.unlock();

            switch (command->mCommand) {
            case CREATE_AUDIO_PATCH: {
                CreateAudioPatchData *data = (CreateAudioPatchData *)command->mData.get();
                ALOGV("CommandThread() processing create audio patch handle %d", data->mHandle);
                mManager.onCreateAudioPatch(data->mHandle, data->mPatch);
                } break;
            case RELEASE_AUDIO_PATCH: {
                ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mData.get();
                ALOGV("CommandThread() processing release audio patch handle %d", data->mHandle);
                mManager.onReleaseAudioPatch(data->mHandle);
                } break;
            default:
                ALOGW("CommandThread() unknown command %d", command->mCommand);
            }
            mLock.lock();
        }

        // At this stage we have either an empty command queue or the first command in the queue
        // has a finite delay. So unless we are exiting it is safe to wait.
        if (!exitPending()) {
            ALOGV("CommandThread() going to sleep");
            mWaitWorkCV.wait(mLock);
        }
    }
    mLock.unlock();
    return false;
}

void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) {
    Mutex::Autolock _l(mLock);
    mCommands.push_back(command);
    mWaitWorkCV.signal();
}

void AudioFlinger::DeviceEffectManager::CommandThread::createAudioPatchCommand(
        audio_patch_handle_t handle, const PatchPanel::Patch& patch)
{
    sp<Command> command = new Command(CREATE_AUDIO_PATCH, new CreateAudioPatchData(handle, patch));
    ALOGV("CommandThread() adding create patch handle %d mHalHandle %d.", handle, patch.mHalHandle);
    sendCommand(command);
}

void AudioFlinger::DeviceEffectManager::CommandThread::releaseAudioPatchCommand(
        audio_patch_handle_t handle)
{
    sp<Command> command = new Command(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
    ALOGV("CommandThread() adding release patch");
    sendCommand(command);
}

void AudioFlinger::DeviceEffectManager::CommandThread::exit()
{
    ALOGV("CommandThread::exit");
    {
        AutoMutex _l(mLock);
        requestExit();
        mWaitWorkCV.signal();
    }
    // Note that we can call it from the thread loop if all other references have been released
    // but it will safely return WOULD_BLOCK in this case
    requestExitAndWait();
}

} // namespace android
+15 −86
Original line number Diff line number Diff line
@@ -20,14 +20,14 @@
#endif

// DeviceEffectManager is concealed within AudioFlinger, their lifetimes are the same.
class DeviceEffectManager {
class DeviceEffectManager : public PatchCommandThread::PatchCommandListener {
public:
    explicit DeviceEffectManager(AudioFlinger* audioFlinger)
        : mCommandThread(new CommandThread(*this)), mAudioFlinger(*audioFlinger),
        mMyCallback(new DeviceEffectManagerCallback(this)) {}
    explicit DeviceEffectManager(AudioFlinger& audioFlinger)
        : mAudioFlinger(audioFlinger),
          mMyCallback(new DeviceEffectManagerCallback(*this)) {}

            ~DeviceEffectManager() {
                mCommandThread->exit();
    void onFirstRef() override {
        mAudioFlinger.mPatchCommandThread->addListener(this);
    }

    sp<EffectHandle> createEffect_l(effect_descriptor_t *descriptor,
@@ -39,8 +39,6 @@ public:
                status_t *status,
                bool probe,
                bool notifyFramesProcessed);
    void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
    void releaseAudioPatch(audio_patch_handle_t handle);

    size_t removeEffect(const sp<DeviceEffectProxy>& effect);
    status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -59,85 +57,16 @@ public:

    void dump(int fd);

private:

    // Thread to execute create and release patch commands asynchronously. This is needed because
    // PatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
    // with mutex locked and effect management requires to call back into audio policy service
    class Command;
    class CommandThread : public Thread {
    public:

        enum {
            CREATE_AUDIO_PATCH,
            RELEASE_AUDIO_PATCH,
        };

        CommandThread(DeviceEffectManager& manager)
            : Thread(false), mManager(manager) {}
        ~CommandThread() override;

        // Thread virtuals
        void onFirstRef() override;
        bool threadLoop() override;

                void exit();
    // PatchCommandThread::PatchCommandListener implementation

                void createAudioPatchCommand(audio_patch_handle_t handle,
                        const PatchPanel::Patch& patch);
                void releaseAudioPatchCommand(audio_patch_handle_t handle);
    void onCreateAudioPatch(audio_patch_handle_t handle,
                            const PatchPanel::Patch& patch) override;
    void onReleaseAudioPatch(audio_patch_handle_t handle) override;

private:
        class CommandData;

        // descriptor for requested tone playback event
        class Command: public RefBase {
        public:
            Command() = default;
            Command(int command, sp<CommandData> data)
                : mCommand(command), mData(data) {}

            int mCommand = -1;
            sp<CommandData> mData;
        };

        class CommandData: public RefBase {
        public:
            virtual ~CommandData() = default;
        };

        class CreateAudioPatchData : public CommandData {
        public:
            CreateAudioPatchData(audio_patch_handle_t handle, const PatchPanel::Patch& patch)
                :   mHandle(handle), mPatch(patch) {}

            audio_patch_handle_t mHandle;
            const PatchPanel::Patch mPatch;
        };

        class ReleaseAudioPatchData : public CommandData {
        public:
            ReleaseAudioPatchData(audio_patch_handle_t handle)
                :   mHandle(handle) {}

            audio_patch_handle_t mHandle;
        };

        void sendCommand(sp<Command> command);

        Mutex   mLock;
        Condition mWaitWorkCV;
        std::deque <sp<Command>> mCommands; // list of pending commands
        DeviceEffectManager& mManager;
    };

    void onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
    void onReleaseAudioPatch(audio_patch_handle_t handle);

    status_t checkEffectCompatibility(const effect_descriptor_t *desc);

    Mutex mLock;
    sp<CommandThread> mCommandThread;
    AudioFlinger &mAudioFlinger;
    const sp<DeviceEffectManagerCallback> mMyCallback;
    std::map<AudioDeviceTypeAddr, sp<DeviceEffectProxy>> mDeviceEffects;
@@ -145,8 +74,8 @@ private:

class DeviceEffectManagerCallback : public EffectCallbackInterface {
public:
            DeviceEffectManagerCallback(DeviceEffectManager *manager)
                : mManager(*manager) {}
    DeviceEffectManagerCallback(DeviceEffectManager& manager)
        : mManager(manager) {}

    status_t createEffectHal(const effect_uuid_t *pEffectUuid,
           int32_t sessionId, int32_t deviceId,
Loading