blob: f4c76d65700f47a713d05b0cb8db378f50590b80 [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
Andy Hung57091702023-07-18 18:31:50 -070021#include "PatchCommandThread.h"
22
23#include <utils/Log.h>
Vlad Popa5161f8a2022-10-10 16:17:20 +020024
25namespace android {
26
27constexpr char kPatchCommandThreadName[] = "AudioFlinger_PatchCommandThread";
28
Andy Hungc8904852023-07-13 19:33:17 -070029PatchCommandThread::~PatchCommandThread() {
Vlad Popa5161f8a2022-10-10 16:17:20 +020030 exit();
31
Andy Hung094dc762023-08-28 19:12:14 -070032 audio_utils::lock_guard _l(mutex());
Vlad Popa5161f8a2022-10-10 16:17:20 +020033 mCommands.clear();
34}
35
Andy Hungc8904852023-07-13 19:33:17 -070036void PatchCommandThread::onFirstRef() {
Vlad Popa5161f8a2022-10-10 16:17:20 +020037 run(kPatchCommandThreadName, ANDROID_PRIORITY_AUDIO);
38}
39
Andy Hungc8904852023-07-13 19:33:17 -070040void PatchCommandThread::addListener(const sp<PatchCommandListener>& listener) {
Vlad Popa5161f8a2022-10-10 16:17:20 +020041 ALOGV("%s add listener %p", __func__, static_cast<void*>(listener.get()));
Andy Hung094dc762023-08-28 19:12:14 -070042 audio_utils::lock_guard _l(listenerMutex());
Vlad Popa5161f8a2022-10-10 16:17:20 +020043 mListeners.emplace_back(listener);
44}
45
Andy Hungc8904852023-07-13 19:33:17 -070046void PatchCommandThread::createAudioPatch(audio_patch_handle_t handle,
Andy Hung07434ef2023-07-13 18:11:33 -070047 const IAfPatchPanel::Patch& patch) {
Vlad Popa5161f8a2022-10-10 16:17:20 +020048 ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
49 __func__, handle, patch.mHalHandle,
50 patch.mAudioPatch.num_sinks,
51 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
52
53 createAudioPatchCommand(handle, patch);
54}
55
Andy Hungc8904852023-07-13 19:33:17 -070056void PatchCommandThread::releaseAudioPatch(audio_patch_handle_t handle) {
Vlad Popa5161f8a2022-10-10 16:17:20 +020057 ALOGV("%s", __func__);
58 releaseAudioPatchCommand(handle);
59}
60
Andy Hungc8904852023-07-13 19:33:17 -070061bool PatchCommandThread::threadLoop()
Andy Hung920f6572022-10-06 12:09:49 -070062{
Andy Hung094dc762023-08-28 19:12:14 -070063 audio_utils::unique_lock _l(mutex());
Vlad Popa5161f8a2022-10-10 16:17:20 +020064
65 while (!exitPending()) {
66 while (!mCommands.empty() && !exitPending()) {
67 const sp<Command> command = mCommands.front();
68 mCommands.pop_front();
69 _l.unlock();
70
71 std::vector<wp<PatchCommandListener>> listenersCopy;
72 {
Andy Hung094dc762023-08-28 19:12:14 -070073 audio_utils::lock_guard _ll(listenerMutex());
Vlad Popa5161f8a2022-10-10 16:17:20 +020074 listenersCopy = mListeners;
75 }
76
77 switch (command->mCommand) {
78 case CREATE_AUDIO_PATCH: {
79 const auto data = (CreateAudioPatchData*) command->mData.get();
80 ALOGV("%s processing create audio patch handle %d",
81 __func__,
82 data->mHandle);
83
84 for (const auto& listener : listenersCopy) {
85 auto spListener = listener.promote();
86 if (spListener) {
87 spListener->onCreateAudioPatch(data->mHandle, data->mPatch);
88 }
89 }
90 }
91 break;
92 case RELEASE_AUDIO_PATCH: {
93 const auto data = (ReleaseAudioPatchData*) command->mData.get();
94 ALOGV("%s processing release audio patch handle %d",
95 __func__,
96 data->mHandle);
97
98 for (const auto& listener : listenersCopy) {
99 auto spListener = listener.promote();
100 if (spListener) {
101 spListener->onReleaseAudioPatch(data->mHandle);
102 }
103 }
104 }
105 break;
106 default:
107 ALOGW("%s unknown command %d", __func__, command->mCommand);
108 break;
109 }
110 _l.lock();
111 }
112
113 // At this stage we have either an empty command queue or the first command in the queue
114 // has a finite delay. So unless we are exiting it is safe to wait.
115 if (!exitPending()) {
116 ALOGV("%s going to sleep", __func__);
117 mWaitWorkCV.wait(_l);
118 }
119 }
120 return false;
121}
122
Andy Hungc8904852023-07-13 19:33:17 -0700123void PatchCommandThread::sendCommand(const sp<Command>& command) {
Andy Hung094dc762023-08-28 19:12:14 -0700124 audio_utils::lock_guard _l(mutex());
Vlad Popa5161f8a2022-10-10 16:17:20 +0200125 mCommands.emplace_back(command);
126 mWaitWorkCV.notify_one();
127}
128
Andy Hungc8904852023-07-13 19:33:17 -0700129void PatchCommandThread::createAudioPatchCommand(
Andy Hung07434ef2023-07-13 18:11:33 -0700130 audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) {
Vlad Popa5161f8a2022-10-10 16:17:20 +0200131 auto command = sp<Command>::make(CREATE_AUDIO_PATCH,
132 new CreateAudioPatchData(handle, patch));
133 ALOGV("%s adding create patch handle %d mHalHandle %d.",
134 __func__,
135 handle,
136 patch.mHalHandle);
137 sendCommand(command);
138}
139
Andy Hungc8904852023-07-13 19:33:17 -0700140void PatchCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle) {
Vlad Popa5161f8a2022-10-10 16:17:20 +0200141 sp<Command> command =
142 sp<Command>::make(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
143 ALOGV("%s adding release patch", __func__);
144 sendCommand(command);
145}
146
Andy Hungc8904852023-07-13 19:33:17 -0700147void PatchCommandThread::exit() {
Vlad Popa5161f8a2022-10-10 16:17:20 +0200148 ALOGV("%s", __func__);
149 {
Andy Hung094dc762023-08-28 19:12:14 -0700150 audio_utils::lock_guard _l(mutex());
Vlad Popa5161f8a2022-10-10 16:17:20 +0200151 requestExit();
152 mWaitWorkCV.notify_one();
153 }
154 // Note that we can call it from the thread loop if all other references have been released
155 // but it will safely return WOULD_BLOCK in this case
156 requestExitAndWait();
157}
158
159} // namespace android