blob: 66018d70354030201fa02be265f7b7ace200ec59 [file] [log] [blame]
Vlad Popa5161f8a2022-10-10 16:17:20 +02001/*
2**
3** Copyright 2022, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Andy Hungd6e86392023-07-13 19:33:17 -070018#pragma once
19
Andy Hungc6f227f2023-07-18 18:31:50 -070020#include "IAfPatchPanel.h"
21
22#include <utils/RefBase.h> // avoid transitive dependency
23#include <utils/Thread.h> // avoid transitive dependency
24
25#include <deque>
26#include <mutex> // avoid transitive dependency
27
Andy Hungd6e86392023-07-13 19:33:17 -070028namespace android {
Vlad Popa5161f8a2022-10-10 16:17:20 +020029
30class Command;
31
32// Thread to execute create and release patch commands asynchronously. This is needed because
Andy Hung8e6b62a2023-07-13 18:11:33 -070033// IAfPatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
Vlad Popa5161f8a2022-10-10 16:17:20 +020034// with mutex locked and effect management requires to call back into audio policy service
35class PatchCommandThread : public Thread {
36public:
37
38 enum {
39 CREATE_AUDIO_PATCH,
40 RELEASE_AUDIO_PATCH,
François Gaffie58e73af2023-02-15 11:47:24 +010041 UPDATE_AUDIO_PATCH,
Vlad Popa5161f8a2022-10-10 16:17:20 +020042 };
43
44 class PatchCommandListener : public virtual RefBase {
45 public:
46 virtual void onCreateAudioPatch(audio_patch_handle_t handle,
Andy Hung8e6b62a2023-07-13 18:11:33 -070047 const IAfPatchPanel::Patch& patch) = 0;
Vlad Popa5161f8a2022-10-10 16:17:20 +020048 virtual void onReleaseAudioPatch(audio_patch_handle_t handle) = 0;
François Gaffie58e73af2023-02-15 11:47:24 +010049 virtual void onUpdateAudioPatch(audio_patch_handle_t oldHandle,
50 audio_patch_handle_t newHandle,
Andy Hung8e6b62a2023-07-13 18:11:33 -070051 const IAfPatchPanel::Patch& patch) = 0;
Vlad Popa5161f8a2022-10-10 16:17:20 +020052 };
53
54 PatchCommandThread() : Thread(false /* canCallJava */) {}
55 ~PatchCommandThread() override;
56
57 void addListener(const sp<PatchCommandListener>& listener);
58
Andy Hung8e6b62a2023-07-13 18:11:33 -070059 void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch);
Vlad Popa5161f8a2022-10-10 16:17:20 +020060 void releaseAudioPatch(audio_patch_handle_t handle);
François Gaffie58e73af2023-02-15 11:47:24 +010061 void updateAudioPatch(audio_patch_handle_t oldHandle,
62 audio_patch_handle_t newHandle,
Andy Hung8e6b62a2023-07-13 18:11:33 -070063 const IAfPatchPanel::Patch& patch);
Vlad Popa5161f8a2022-10-10 16:17:20 +020064
65 // Thread virtuals
66 void onFirstRef() override;
67 bool threadLoop() override;
68
69 void exit();
70
71 void createAudioPatchCommand(audio_patch_handle_t handle,
Andy Hung8e6b62a2023-07-13 18:11:33 -070072 const IAfPatchPanel::Patch& patch);
Vlad Popa5161f8a2022-10-10 16:17:20 +020073 void releaseAudioPatchCommand(audio_patch_handle_t handle);
François Gaffie58e73af2023-02-15 11:47:24 +010074 void updateAudioPatchCommand(audio_patch_handle_t oldHandle,
75 audio_patch_handle_t newHandle,
Andy Hung8e6b62a2023-07-13 18:11:33 -070076 const IAfPatchPanel::Patch& patch);
Vlad Popa5161f8a2022-10-10 16:17:20 +020077private:
78 class CommandData;
79
80 // Command type received from the PatchPanel
81 class Command: public RefBase {
82 public:
83 Command() = default;
84 Command(int command, const sp<CommandData>& data)
85 : mCommand(command), mData(data) {}
86
87 const int mCommand = -1;
88 const sp<CommandData> mData;
89 };
90
91 class CommandData: public RefBase {};
92
93 class CreateAudioPatchData : public CommandData {
94 public:
Andy Hung8e6b62a2023-07-13 18:11:33 -070095 CreateAudioPatchData(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
Vlad Popa5161f8a2022-10-10 16:17:20 +020096 : mHandle(handle), mPatch(patch) {}
97
98 const audio_patch_handle_t mHandle;
Andy Hung8e6b62a2023-07-13 18:11:33 -070099 const IAfPatchPanel::Patch mPatch;
Vlad Popa5161f8a2022-10-10 16:17:20 +0200100 };
101
102 class ReleaseAudioPatchData : public CommandData {
103 public:
Andy Hungf9829e42022-10-06 12:09:49 -0700104 explicit ReleaseAudioPatchData(audio_patch_handle_t handle)
Vlad Popa5161f8a2022-10-10 16:17:20 +0200105 : mHandle(handle) {}
106
107 audio_patch_handle_t mHandle;
108 };
109
François Gaffie58e73af2023-02-15 11:47:24 +0100110 class UpdateAudioPatchData : public CommandData {
111 public:
112 UpdateAudioPatchData(audio_patch_handle_t oldHandle,
113 audio_patch_handle_t newHandle,
Andy Hung8e6b62a2023-07-13 18:11:33 -0700114 const IAfPatchPanel::Patch& patch)
François Gaffie58e73af2023-02-15 11:47:24 +0100115 : mOldHandle(oldHandle), mNewHandle(newHandle), mPatch(patch) {}
116
117 const audio_patch_handle_t mOldHandle;
118 const audio_patch_handle_t mNewHandle;
Andy Hung8e6b62a2023-07-13 18:11:33 -0700119 const IAfPatchPanel::Patch mPatch;
François Gaffie58e73af2023-02-15 11:47:24 +0100120 };
121
Vlad Popa5161f8a2022-10-10 16:17:20 +0200122 void sendCommand(const sp<Command>& command);
123
124 std::string mThreadName;
125 std::mutex mLock;
126 std::condition_variable mWaitWorkCV;
127 std::deque<sp<Command>> mCommands GUARDED_BY(mLock); // list of pending commands
128
129 std::mutex mListenerLock;
130 std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(mListenerLock);
131};
Andy Hungd6e86392023-07-13 19:33:17 -0700132
133} // namespace android