blob: c316d8a08a64b251372823987a031f3f91ba2f9b [file] [log] [blame]
/*
**
** Copyright 2022, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#pragma once
#include "IAfPatchPanel.h"
#include <utils/RefBase.h> // avoid transitive dependency
#include <utils/Thread.h> // avoid transitive dependency
#include <deque>
#include <mutex> // avoid transitive dependency
namespace android {
class Command;
// Thread to execute create and release patch commands asynchronously. This is needed because
// IAfPatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
// with mutex locked and effect management requires to call back into audio policy service
class PatchCommandThread : public Thread {
public:
enum {
CREATE_AUDIO_PATCH,
RELEASE_AUDIO_PATCH,
UPDATE_AUDIO_PATCH,
};
class PatchCommandListener : public virtual RefBase {
public:
virtual void onCreateAudioPatch(audio_patch_handle_t handle,
const IAfPatchPanel::Patch& patch) = 0;
virtual void onReleaseAudioPatch(audio_patch_handle_t handle) = 0;
virtual void onUpdateAudioPatch(audio_patch_handle_t oldHandle,
audio_patch_handle_t newHandle,
const IAfPatchPanel::Patch& patch) = 0;
};
PatchCommandThread() : Thread(false /* canCallJava */) {}
~PatchCommandThread() override;
void addListener(const sp<PatchCommandListener>& listener)
EXCLUDES_PatchCommandThread_ListenerMutex;
void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
EXCLUDES_PatchCommandThread_Mutex;
void releaseAudioPatch(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
void updateAudioPatch(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle,
const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
// Thread virtuals
void onFirstRef() override;
bool threadLoop() override;
void exit();
void createAudioPatchCommand(audio_patch_handle_t handle,
const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
void releaseAudioPatchCommand(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
void updateAudioPatchCommand(audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle,
const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
private:
class CommandData;
// Command type received from the PatchPanel
class Command: public RefBase {
public:
Command() = default;
Command(int command, const sp<CommandData>& data)
: mCommand(command), mData(data) {}
const int mCommand = -1;
const sp<CommandData> mData;
};
class CommandData: public RefBase {};
class CreateAudioPatchData : public CommandData {
public:
CreateAudioPatchData(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
: mHandle(handle), mPatch(patch) {}
const audio_patch_handle_t mHandle;
const IAfPatchPanel::Patch mPatch;
};
class ReleaseAudioPatchData : public CommandData {
public:
explicit ReleaseAudioPatchData(audio_patch_handle_t handle)
: mHandle(handle) {}
audio_patch_handle_t mHandle;
};
class UpdateAudioPatchData : public CommandData {
public:
UpdateAudioPatchData(audio_patch_handle_t oldHandle,
audio_patch_handle_t newHandle,
const IAfPatchPanel::Patch& patch)
: mOldHandle(oldHandle), mNewHandle(newHandle), mPatch(patch) {}
const audio_patch_handle_t mOldHandle;
const audio_patch_handle_t mNewHandle;
const IAfPatchPanel::Patch mPatch;
};
void sendCommand(const sp<Command>& command) EXCLUDES_PatchCommandThread_Mutex;
audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::PatchCommandThread_Mutex) {
return mMutex;
}
audio_utils::mutex& listenerMutex() const
RETURN_CAPABILITY(audio_utils::PatchCommandThread_ListenerMutex) {
return mListenerMutex;
}
mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kPatchCommandThread_Mutex};
audio_utils::condition_variable mWaitWorkCV;
std::deque<sp<Command>> mCommands GUARDED_BY(mutex()); // list of pending commands
mutable audio_utils::mutex mListenerMutex{
audio_utils::MutexOrder::kPatchCommandThread_ListenerMutex};
std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(listenerMutex());
};
} // namespace android