blob: 858784d3f07a3a78784b99dafed1130740851b16 [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
18#define LOG_TAG "AudioFlinger::PatchCommandThread"
19//#define LOG_NDEBUG 0
20
21#include "AudioFlinger.h"
22
23namespace android {
24
25constexpr char kPatchCommandThreadName[] = "AudioFlinger_PatchCommandThread";
26
27AudioFlinger::PatchCommandThread::~PatchCommandThread() {
28 exit();
29
30 std::lock_guard _l(mLock);
31 mCommands.clear();
32}
33
34void AudioFlinger::PatchCommandThread::onFirstRef() {
35 run(kPatchCommandThreadName, ANDROID_PRIORITY_AUDIO);
36}
37
38void 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
44void 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
54void AudioFlinger::PatchCommandThread::releaseAudioPatch(audio_patch_handle_t handle) {
55 ALOGV("%s", __func__);
56 releaseAudioPatchCommand(handle);
57}
58
François Gaffie58e73af2023-02-15 11:47:24 +010059void AudioFlinger::PatchCommandThread::updateAudioPatch(audio_patch_handle_t oldHandle,
60 audio_patch_handle_t newHandle, const PatchPanel::Patch& patch) {
61 ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
62 __func__, oldHandle, patch.mHalHandle,
63 patch.mAudioPatch.num_sinks,
64 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
65
66 updateAudioPatchCommand(oldHandle, newHandle, patch);
67}
68
Andy Hungf9829e42022-10-06 12:09:49 -070069bool AudioFlinger::PatchCommandThread::threadLoop()
70NO_THREAD_SAFETY_ANALYSIS // bug in clang compiler.
71{
Vlad Popa5161f8a2022-10-10 16:17:20 +020072 std::unique_lock _l(mLock);
73
74 while (!exitPending()) {
75 while (!mCommands.empty() && !exitPending()) {
76 const sp<Command> command = mCommands.front();
77 mCommands.pop_front();
78 _l.unlock();
79
80 std::vector<wp<PatchCommandListener>> listenersCopy;
81 {
82 std::lock_guard _ll(mListenerLock);
83 listenersCopy = mListeners;
84 }
85
86 switch (command->mCommand) {
87 case CREATE_AUDIO_PATCH: {
88 const auto data = (CreateAudioPatchData*) command->mData.get();
89 ALOGV("%s processing create audio patch handle %d",
90 __func__,
91 data->mHandle);
92
93 for (const auto& listener : listenersCopy) {
94 auto spListener = listener.promote();
95 if (spListener) {
96 spListener->onCreateAudioPatch(data->mHandle, data->mPatch);
97 }
98 }
99 }
100 break;
101 case RELEASE_AUDIO_PATCH: {
102 const auto data = (ReleaseAudioPatchData*) command->mData.get();
103 ALOGV("%s processing release audio patch handle %d",
104 __func__,
105 data->mHandle);
106
107 for (const auto& listener : listenersCopy) {
108 auto spListener = listener.promote();
109 if (spListener) {
110 spListener->onReleaseAudioPatch(data->mHandle);
111 }
112 }
113 }
114 break;
François Gaffie58e73af2023-02-15 11:47:24 +0100115 case UPDATE_AUDIO_PATCH: {
116 const auto data = (UpdateAudioPatchData*) command->mData.get();
117 ALOGV("%s processing update audio patch old handle %d new handle %d",
118 __func__,
119 data->mOldHandle, data->mNewHandle);
120
121 for (const auto& listener : listenersCopy) {
122 auto spListener = listener.promote();
123 if (spListener) {
124 spListener->onUpdateAudioPatch(data->mOldHandle,
125 data->mNewHandle, data->mPatch);
126 }
127 }
128 }
129 break;
Vlad Popa5161f8a2022-10-10 16:17:20 +0200130 default:
131 ALOGW("%s unknown command %d", __func__, command->mCommand);
132 break;
133 }
134 _l.lock();
135 }
136
137 // At this stage we have either an empty command queue or the first command in the queue
138 // has a finite delay. So unless we are exiting it is safe to wait.
139 if (!exitPending()) {
140 ALOGV("%s going to sleep", __func__);
141 mWaitWorkCV.wait(_l);
142 }
143 }
144 return false;
145}
146
147void AudioFlinger::PatchCommandThread::sendCommand(const sp<Command>& command) {
148 std::lock_guard _l(mLock);
149 mCommands.emplace_back(command);
150 mWaitWorkCV.notify_one();
151}
152
153void AudioFlinger::PatchCommandThread::createAudioPatchCommand(
154 audio_patch_handle_t handle, const PatchPanel::Patch& patch) {
155 auto command = sp<Command>::make(CREATE_AUDIO_PATCH,
156 new CreateAudioPatchData(handle, patch));
157 ALOGV("%s adding create patch handle %d mHalHandle %d.",
158 __func__,
159 handle,
160 patch.mHalHandle);
161 sendCommand(command);
162}
163
164void AudioFlinger::PatchCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle) {
165 sp<Command> command =
166 sp<Command>::make(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
167 ALOGV("%s adding release patch", __func__);
168 sendCommand(command);
169}
170
François Gaffie58e73af2023-02-15 11:47:24 +0100171void AudioFlinger::PatchCommandThread::updateAudioPatchCommand(
172 audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle,
173 const PatchPanel::Patch& patch) {
174 sp<Command> command = sp<Command>::make(UPDATE_AUDIO_PATCH,
175 new UpdateAudioPatchData(oldHandle, newHandle, patch));
176 ALOGV("%s adding update patch old handle %d new handle %d mHalHandle %d.",
177 __func__, oldHandle, newHandle, patch.mHalHandle);
178 sendCommand(command);
179}
180
Vlad Popa5161f8a2022-10-10 16:17:20 +0200181void AudioFlinger::PatchCommandThread::exit() {
182 ALOGV("%s", __func__);
183 {
184 std::lock_guard _l(mLock);
185 requestExit();
186 mWaitWorkCV.notify_one();
187 }
188 // Note that we can call it from the thread loop if all other references have been released
189 // but it will safely return WOULD_BLOCK in this case
190 requestExitAndWait();
191}
192
193} // namespace android