• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
18 #define LOG_TAG "AudioFlinger::PatchCommandThread"
19 //#define LOG_NDEBUG 0
20 
21 #include "AudioFlinger.h"
22 
23 namespace android {
24 
25 constexpr char kPatchCommandThreadName[] = "AudioFlinger_PatchCommandThread";
26 
~PatchCommandThread()27 AudioFlinger::PatchCommandThread::~PatchCommandThread() {
28     exit();
29 
30     std::lock_guard _l(mLock);
31     mCommands.clear();
32 }
33 
onFirstRef()34 void AudioFlinger::PatchCommandThread::onFirstRef() {
35     run(kPatchCommandThreadName, ANDROID_PRIORITY_AUDIO);
36 }
37 
addListener(const sp<PatchCommandListener> & listener)38 void AudioFlinger::PatchCommandThread::addListener(const sp<PatchCommandListener>& listener) {
39     ALOGV("%s add listener %p", __func__, static_cast<void*>(listener.get()));
40     std::lock_guard _l(mListenerLock);
41     mListeners.emplace_back(listener);
42 }
43 
createAudioPatch(audio_patch_handle_t handle,const PatchPanel::Patch & patch)44 void AudioFlinger::PatchCommandThread::createAudioPatch(audio_patch_handle_t handle,
45         const PatchPanel::Patch& patch) {
46     ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
47             __func__, handle, patch.mHalHandle,
48             patch.mAudioPatch.num_sinks,
49             patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
50 
51     createAudioPatchCommand(handle, patch);
52 }
53 
releaseAudioPatch(audio_patch_handle_t handle)54 void AudioFlinger::PatchCommandThread::releaseAudioPatch(audio_patch_handle_t handle) {
55     ALOGV("%s", __func__);
56     releaseAudioPatchCommand(handle);
57 }
58 
threadLoop()59 bool AudioFlinger::PatchCommandThread::threadLoop()
60 NO_THREAD_SAFETY_ANALYSIS  // bug in clang compiler.
61 {
62     std::unique_lock _l(mLock);
63 
64     while (!exitPending()) {
65         while (!mCommands.empty() && !exitPending()) {
66             const sp<Command> command = mCommands.front();
67             mCommands.pop_front();
68             _l.unlock();
69 
70             std::vector<wp<PatchCommandListener>> listenersCopy;
71             {
72                 std::lock_guard _ll(mListenerLock);
73                 listenersCopy = mListeners;
74             }
75 
76             switch (command->mCommand) {
77                 case CREATE_AUDIO_PATCH: {
78                     const auto data = (CreateAudioPatchData*) command->mData.get();
79                     ALOGV("%s processing create audio patch handle %d",
80                           __func__,
81                           data->mHandle);
82 
83                     for (const auto& listener : listenersCopy) {
84                         auto spListener = listener.promote();
85                         if (spListener) {
86                             spListener->onCreateAudioPatch(data->mHandle, data->mPatch);
87                         }
88                     }
89                 }
90                     break;
91                 case RELEASE_AUDIO_PATCH: {
92                     const auto data = (ReleaseAudioPatchData*) command->mData.get();
93                     ALOGV("%s processing release audio patch handle %d",
94                           __func__,
95                           data->mHandle);
96 
97                     for (const auto& listener : listenersCopy) {
98                         auto spListener = listener.promote();
99                         if (spListener) {
100                             spListener->onReleaseAudioPatch(data->mHandle);
101                         }
102                     }
103                 }
104                     break;
105                 default:
106                     ALOGW("%s unknown command %d", __func__, command->mCommand);
107                     break;
108             }
109             _l.lock();
110         }
111 
112         // At this stage we have either an empty command queue or the first command in the queue
113         // has a finite delay. So unless we are exiting it is safe to wait.
114         if (!exitPending()) {
115             ALOGV("%s going to sleep", __func__);
116             mWaitWorkCV.wait(_l);
117         }
118     }
119     return false;
120 }
121 
sendCommand(const sp<Command> & command)122 void AudioFlinger::PatchCommandThread::sendCommand(const sp<Command>& command) {
123     std::lock_guard _l(mLock);
124     mCommands.emplace_back(command);
125     mWaitWorkCV.notify_one();
126 }
127 
createAudioPatchCommand(audio_patch_handle_t handle,const PatchPanel::Patch & patch)128 void AudioFlinger::PatchCommandThread::createAudioPatchCommand(
129         audio_patch_handle_t handle, const PatchPanel::Patch& patch) {
130     auto command = sp<Command>::make(CREATE_AUDIO_PATCH,
131                                      new CreateAudioPatchData(handle, patch));
132     ALOGV("%s adding create patch handle %d mHalHandle %d.",
133           __func__,
134           handle,
135           patch.mHalHandle);
136     sendCommand(command);
137 }
138 
releaseAudioPatchCommand(audio_patch_handle_t handle)139 void AudioFlinger::PatchCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle) {
140     sp<Command> command =
141         sp<Command>::make(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
142     ALOGV("%s adding release patch", __func__);
143     sendCommand(command);
144 }
145 
exit()146 void AudioFlinger::PatchCommandThread::exit() {
147     ALOGV("%s", __func__);
148     {
149         std::lock_guard _l(mLock);
150         requestExit();
151         mWaitWorkCV.notify_one();
152     }
153     // Note that we can call it from the thread loop if all other references have been released
154     // but it will safely return WOULD_BLOCK in this case
155     requestExitAndWait();
156 }
157 
158 }  // namespace android
159