blob: 1d38306cc0c94cec746fac5ea9ebad8e88476e7c [file] [log] [blame]
Vlad Popab042ee62022-10-20 18:05:00 +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_NDEBUG 0
Andy Hungad2faf72023-07-13 20:00:50 -070019#define LOG_TAG "MelReporter"
Vlad Popab042ee62022-10-20 18:05:00 +020020
Andy Hungba8b63b2023-07-18 18:55:52 -070021#include "MelReporter.h"
Vlad Popab042ee62022-10-20 18:05:00 +020022
Vlad Popa63f047e2022-11-05 14:09:19 +010023#include <android/media/ISoundDoseCallback.h>
Vlad Popa2900c0a2022-10-24 13:38:00 +020024#include <audio_utils/power.h>
25#include <utils/Log.h>
26
Vlad Popadebe0a72022-12-28 16:55:13 +010027using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Vlad Popa1d5f0d52022-12-18 12:21:26 +010028
Vlad Popab042ee62022-10-20 18:05:00 +020029namespace android {
30
Andy Hungad2faf72023-07-13 20:00:50 -070031bool MelReporter::activateHalSoundDoseComputation(const std::string& module,
Vlad Popa03bd5bc2023-01-17 16:16:51 +010032 const sp<DeviceHalInterface>& device) {
Vlad Popaeb8036a2023-09-29 18:20:04 -070033 if (mSoundDoseManager->isFrameworkMelForced()) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010034 ALOGD("%s: Forcing use of internal MEL computation.", __func__);
35 activateInternalSoundDoseComputation();
36 return false;
37 }
38
Vlad Popa03bd5bc2023-01-17 16:16:51 +010039 ndk::SpAIBinder soundDoseBinder;
40 if (device->getSoundDoseInterface(module, &soundDoseBinder) != OK) {
Vlad Popab1c53782023-08-21 19:52:14 -070041 ALOGW("%s: HAL cannot provide sound dose interface for module %s",
Vlad Popa1d5f0d52022-12-18 12:21:26 +010042 __func__, module.c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +010043 return false;
44 }
45
Vlad Popa03bd5bc2023-01-17 16:16:51 +010046 if (soundDoseBinder == nullptr) {
Vlad Popab1c53782023-08-21 19:52:14 -070047 ALOGW("%s: HAL doesn't implement a sound dose interface for module %s",
Vlad Popa03bd5bc2023-01-17 16:16:51 +010048 __func__, module.c_str());
Vlad Popa03bd5bc2023-01-17 16:16:51 +010049 return false;
50 }
51
52 std::shared_ptr<ISoundDose> soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder);
53
Vlad Popab1c53782023-08-21 19:52:14 -070054 if (!mSoundDoseManager->setHalSoundDoseInterface(module, soundDoseInterface)) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010055 ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +010056 return false;
57 }
58
Vlad Popa1d5f0d52022-12-18 12:21:26 +010059 stopInternalMelComputation();
60 return true;
61}
62
Andy Hungad2faf72023-07-13 20:00:50 -070063void MelReporter::activateInternalSoundDoseComputation() {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010064 {
Andy Hung0169fbc2023-08-28 19:12:14 -070065 audio_utils::lock_guard _l(mutex());
Vlad Popa3d6d39d2022-12-21 18:59:16 +010066 if (!mUseHalSoundDoseInterface) {
67 // no need to start internal MEL on active patches
68 return;
69 }
70 mUseHalSoundDoseInterface = false;
71 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +010072
Vlad Popab1c53782023-08-21 19:52:14 -070073 // reset the HAL interfaces and use internal MELs
74 mSoundDoseManager->resetHalSoundDoseInterfaces();
Vlad Popa1d5f0d52022-12-18 12:21:26 +010075}
76
Andy Hungad2faf72023-07-13 20:00:50 -070077void MelReporter::onFirstRef() {
Andy Hungb60a2c82023-07-17 14:02:52 -070078 mAfMelReporterCallback->getPatchCommandThread()->addListener(this);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010079
Vlad Popaf79f6ba2023-07-27 18:27:59 -070080 mSoundDoseManager = sp<SoundDoseManager>::make(sp<IMelReporterCallback>::fromExisting(this));
Vlad Popab042ee62022-10-20 18:05:00 +020081}
82
Andy Hungad2faf72023-07-13 20:00:50 -070083void MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
Vlad Popa7e81cea2023-01-19 16:34:16 +010084 const std::vector<playback_track_metadata_v7_t>& metadataVec) {
Vlad Popa617bbf02023-04-24 19:10:36 +020085 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +010086 ALOGV("%s csd is disabled", __func__);
87 return;
88 }
89
Andy Hung77448a52023-09-06 17:52:01 -070090 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hung0169fbc2023-08-28 19:12:14 -070091 audio_utils::lock_guard _l(mutex());
Vlad Popa7e81cea2023-01-19 16:34:16 +010092 auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
93 if (!activeMelPatchId) {
94 ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
95 return;
96 }
97
98 bool shouldActivateCsd = false;
99 for (const auto& metadata : metadataVec) {
100 if (metadata.base.usage == AUDIO_USAGE_GAME || metadata.base.usage == AUDIO_USAGE_MEDIA) {
101 shouldActivateCsd = true;
102 }
103 }
104
105 auto activeMelPatchIt = mActiveMelPatches.find(activeMelPatchId.value());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700106 if (activeMelPatchIt != mActiveMelPatches.end()) {
107 if (shouldActivateCsd != activeMelPatchIt->second.csdActive) {
108 if (activeMelPatchIt->second.csdActive) {
109 ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle);
110 stopMelComputationForPatch_l(activeMelPatchIt->second);
111 } else {
112 ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle);
113 startMelComputationForActivePatch_l(activeMelPatchIt->second);
114 }
115 activeMelPatchIt->second.csdActive = shouldActivateCsd;
Vlad Popa7e81cea2023-01-19 16:34:16 +0100116 }
Vlad Popa7e81cea2023-01-19 16:34:16 +0100117 }
118}
119
Andy Hungad2faf72023-07-13 20:00:50 -0700120void MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
Andy Hung8e6b62a2023-07-13 18:11:33 -0700121 const IAfPatchPanel::Patch& patch) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200122 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100123 ALOGV("%s csd is disabled", __func__);
124 return;
125 }
Vlad Popa7e81cea2023-01-19 16:34:16 +0100126
Vlad Popab042ee62022-10-20 18:05:00 +0200127 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
128 __func__, handle, patch.mHalHandle,
129 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
130 if (patch.mAudioPatch.num_sources == 0
131 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100132 ALOGV("%s: patch does not contain any mix sources", __func__);
Vlad Popab042ee62022-10-20 18:05:00 +0200133 return;
134 }
135
136 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
137 ActiveMelPatch newPatch;
138 newPatch.streamHandle = streamHandle;
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700139 newPatch.csdActive = false;
Andy Hung920f6572022-10-06 12:09:49 -0700140 for (size_t i = 0; i < patch.mAudioPatch.num_sinks; ++i) {
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700141 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE &&
142 mSoundDoseManager->shouldComputeCsdForDeviceType(
143 patch.mAudioPatch.sinks[i].ext.device.type)) {
Vlad Popab042ee62022-10-20 18:05:00 +0200144 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700145 bool shouldComputeCsd = mSoundDoseManager->shouldComputeCsdForDeviceWithAddress(
146 patch.mAudioPatch.sinks[i].ext.device.type,
147 patch.mAudioPatch.sinks[i].ext.device.address);
148 newPatch.deviceStates.push_back({deviceId, shouldComputeCsd});
149 newPatch.csdActive |= shouldComputeCsd;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100150 AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
151 patch.mAudioPatch.sinks[i].ext.device.address};
152 mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200153 }
154 }
155
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700156 if (!newPatch.deviceStates.empty() && newPatch.csdActive) {
Andy Hung77448a52023-09-06 17:52:01 -0700157 audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hung0169fbc2023-08-28 19:12:14 -0700158 audio_utils::lock_guard _l(mutex());
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200159 ALOGV("%s add patch handle %d to active devices", __func__, handle);
160 startMelComputationForActivePatch_l(newPatch);
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200161 mActiveMelPatches[handle] = newPatch;
162 }
Vlad Popab042ee62022-10-20 18:05:00 +0200163}
164
Andy Hungad2faf72023-07-13 20:00:50 -0700165void MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
Andy Hung920f6572022-10-06 12:09:49 -0700166NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
167{
Andy Hungb60a2c82023-07-17 14:02:52 -0700168 auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100169 if (outputThread == nullptr) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100170 ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
171 return;
172 }
173
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700174 for (const auto& device : patch.deviceStates) {
175 if (device.second) {
176 ++mActiveDevices[device.first];
177 ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
178 patch.streamHandle, device.first, mActiveDevices[device.first]);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100179
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700180 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
181 outputThread->startMelComputation_l(
182 mSoundDoseManager->getOrCreateProcessorForDevice(
183 device.first,
184 patch.streamHandle,
185 outputThread->sampleRate(),
186 outputThread->channelCount(),
187 outputThread->format()));
188 }
189 }
190 }
191}
192
193void MelReporter::startMelComputationForDeviceId(audio_port_handle_t deviceId) {
194 ALOGV("%s(%d)", __func__, deviceId);
Andy Hung0169fbc2023-08-28 19:12:14 -0700195 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
196 audio_utils::lock_guard _l(mutex());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700197
198 for (auto& activeMelPatch : mActiveMelPatches) {
199 bool csdActive = false;
200 for (auto& device: activeMelPatch.second.deviceStates) {
201 if (device.first == deviceId && !device.second) {
202 device.second = true;
203 }
204 csdActive |= device.second;
205 }
206 if (csdActive && !activeMelPatch.second.csdActive) {
207 activeMelPatch.second.csdActive = csdActive;
208 startMelComputationForActivePatch_l(activeMelPatch.second);
Vlad Popa7e81cea2023-01-19 16:34:16 +0100209 }
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100210 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100211}
212
Andy Hungad2faf72023-07-13 20:00:50 -0700213void MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200214 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100215 ALOGV("%s csd is disabled", __func__);
216 return;
217 }
218
Vlad Popab042ee62022-10-20 18:05:00 +0200219 ActiveMelPatch melPatch;
220 {
Andy Hung0169fbc2023-08-28 19:12:14 -0700221 audio_utils::lock_guard _l(mutex());
Vlad Popab042ee62022-10-20 18:05:00 +0200222
223 auto patchIt = mActiveMelPatches.find(handle);
224 if (patchIt == mActiveMelPatches.end()) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100225 ALOGV("%s patch handle %d does not contain any mix sources with active MEL calculation",
226 __func__, handle);
Vlad Popab042ee62022-10-20 18:05:00 +0200227 return;
228 }
229
230 melPatch = patchIt->second;
231 mActiveMelPatches.erase(patchIt);
232 }
233
Andy Hung77448a52023-09-06 17:52:01 -0700234 audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hung0169fbc2023-08-28 19:12:14 -0700235 audio_utils::lock_guard _l(mutex());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700236 if (melPatch.csdActive) {
237 // only need to stop if patch was active
238 melPatch.csdActive = false;
239 stopMelComputationForPatch_l(melPatch);
240 }
Vlad Popab042ee62022-10-20 18:05:00 +0200241}
242
Andy Hungad2faf72023-07-13 20:00:50 -0700243void MelReporter::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
Andy Hung8e6b62a2023-07-13 18:11:33 -0700244 audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
François Gaffie58e73af2023-02-15 11:47:24 +0100245 onReleaseAudioPatch(oldHandle);
246 onCreateAudioPatch(newHandle, patch);
247}
248
Andy Hungad2faf72023-07-13 20:00:50 -0700249sp<media::ISoundDose> MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100250 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100251 // no need to lock since getSoundDoseInterface is synchronized
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100252 return mSoundDoseManager->getSoundDoseInterface(callback);
253}
254
Andy Hungad2faf72023-07-13 20:00:50 -0700255void MelReporter::stopInternalMelComputation() {
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100256 ALOGV("%s", __func__);
Andy Hung0169fbc2023-08-28 19:12:14 -0700257 audio_utils::lock_guard _l(mutex());
Vlad Popab1c53782023-08-21 19:52:14 -0700258 if (mUseHalSoundDoseInterface) {
259 return;
260 }
Vlad Popa870f6d62022-12-22 12:15:47 +0100261 mActiveMelPatches.clear();
262 mUseHalSoundDoseInterface = true;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100263}
264
Andy Hungad2faf72023-07-13 20:00:50 -0700265void MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
Andy Hung920f6572022-10-06 12:09:49 -0700266NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
267{
Andy Hungb60a2c82023-07-17 14:02:52 -0700268 auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100269
Vlad Popa7e81cea2023-01-19 16:34:16 +0100270 ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700271 for (const auto& device : patch.deviceStates) {
272 if (mActiveDevices[device.first] > 0) {
273 --mActiveDevices[device.first];
274 if (mActiveDevices[device.first] == 0) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100275 // no stream is using deviceId anymore
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700276 ALOGI("%s removing device %d from active CSD devices", __func__, device.first);
277 mSoundDoseManager->clearMapDeviceIdEntries(device.first);
Vlad Popa7e81cea2023-01-19 16:34:16 +0100278 }
279 }
280 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100281
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700282 mSoundDoseManager->removeStreamProcessor(patch.streamHandle);
Vlad Popa69fbbee2023-04-25 12:23:24 +0200283 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100284 outputThread->stopMelComputation_l();
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100285 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100286}
287
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700288void MelReporter::stopMelComputationForDeviceId(audio_port_handle_t deviceId) {
289 ALOGV("%s(%d)", __func__, deviceId);
Andy Hung0169fbc2023-08-28 19:12:14 -0700290 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
291 audio_utils::lock_guard _l(mutex());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700292
293 for (auto& activeMelPatch : mActiveMelPatches) {
294 bool csdActive = false;
295 for (auto& device: activeMelPatch.second.deviceStates) {
296 if (device.first == deviceId && device.second) {
297 device.second = false;
298 }
299 csdActive |= device.second;
300 }
301
302 if (!csdActive && activeMelPatch.second.csdActive) {
303 activeMelPatch.second.csdActive = csdActive;
304 stopMelComputationForPatch_l(activeMelPatch.second);
305 }
306 }
307
308}
Vlad Popa7e81cea2023-01-19 16:34:16 +0100309
Vlad Popa1c67ad62024-01-19 17:53:42 -0800310void MelReporter::applyAllAudioPatches() {
311 ALOGV("%s", __func__);
312
313 std::vector<IAfPatchPanel::Patch> patchesCopy;
314 {
315 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
316 for (const auto& patch : mAfPatchPanel->patches_l()) {
317 patchesCopy.emplace_back(patch.second);
318 }
319 }
320
321 for (const auto& patch : patchesCopy) {
322 onCreateAudioPatch(patch.mHalHandle, patch);
323 }
324}
325
Andy Hungad2faf72023-07-13 20:00:50 -0700326std::optional<audio_patch_handle_t> MelReporter::activePatchStreamHandle_l(
Vlad Popa7e81cea2023-01-19 16:34:16 +0100327 audio_io_handle_t streamHandle) {
328 for(const auto& patchIt : mActiveMelPatches) {
329 if (patchIt.second.streamHandle == streamHandle) {
330 return patchIt.first;
331 }
332 }
333 return std::nullopt;
334}
335
Andy Hungad2faf72023-07-13 20:00:50 -0700336bool MelReporter::useHalSoundDoseInterface_l() {
Vlad Popaeb8036a2023-09-29 18:20:04 -0700337 return !mSoundDoseManager->isFrameworkMelForced() & mUseHalSoundDoseInterface;
Vlad Popa7e81cea2023-01-19 16:34:16 +0100338}
339
Andy Hungad2faf72023-07-13 20:00:50 -0700340std::string MelReporter::dump() {
Andy Hung0169fbc2023-08-28 19:12:14 -0700341 audio_utils::lock_guard _l(mutex());
Vlad Popa2900c0a2022-10-24 13:38:00 +0200342 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100343 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200344 return output;
345}
346
347} // namespace android