blob: 57f4ff6b9f76dcf670f5c420b664da06d0233e6e [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
Shraddha Basantwanifd414a82024-06-06 16:28:52 +0000120void MelReporter::resetReferencesForTest() {
121 mAfMelReporterCallback.clear();
122 mSoundDoseManager->resetReferencesForTest();
123}
124
Andy Hungad2faf72023-07-13 20:00:50 -0700125void MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
Andy Hung8e6b62a2023-07-13 18:11:33 -0700126 const IAfPatchPanel::Patch& patch) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200127 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100128 ALOGV("%s csd is disabled", __func__);
129 return;
130 }
Vlad Popa7e81cea2023-01-19 16:34:16 +0100131
Vlad Popab042ee62022-10-20 18:05:00 +0200132 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
133 __func__, handle, patch.mHalHandle,
134 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
135 if (patch.mAudioPatch.num_sources == 0
136 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100137 ALOGV("%s: patch does not contain any mix sources", __func__);
Vlad Popab042ee62022-10-20 18:05:00 +0200138 return;
139 }
140
141 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
142 ActiveMelPatch newPatch;
143 newPatch.streamHandle = streamHandle;
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700144 newPatch.csdActive = false;
Andy Hung920f6572022-10-06 12:09:49 -0700145 for (size_t i = 0; i < patch.mAudioPatch.num_sinks; ++i) {
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700146 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE &&
147 mSoundDoseManager->shouldComputeCsdForDeviceType(
148 patch.mAudioPatch.sinks[i].ext.device.type)) {
Vlad Popab042ee62022-10-20 18:05:00 +0200149 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700150 bool shouldComputeCsd = mSoundDoseManager->shouldComputeCsdForDeviceWithAddress(
151 patch.mAudioPatch.sinks[i].ext.device.type,
152 patch.mAudioPatch.sinks[i].ext.device.address);
153 newPatch.deviceStates.push_back({deviceId, shouldComputeCsd});
154 newPatch.csdActive |= shouldComputeCsd;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100155 AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
156 patch.mAudioPatch.sinks[i].ext.device.address};
157 mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200158 }
159 }
160
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700161 if (!newPatch.deviceStates.empty() && newPatch.csdActive) {
Andy Hung77448a52023-09-06 17:52:01 -0700162 audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hung0169fbc2023-08-28 19:12:14 -0700163 audio_utils::lock_guard _l(mutex());
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200164 ALOGV("%s add patch handle %d to active devices", __func__, handle);
165 startMelComputationForActivePatch_l(newPatch);
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200166 mActiveMelPatches[handle] = newPatch;
167 }
Vlad Popab042ee62022-10-20 18:05:00 +0200168}
169
Andy Hungad2faf72023-07-13 20:00:50 -0700170void MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
Andy Hung920f6572022-10-06 12:09:49 -0700171NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
172{
Andy Hungb60a2c82023-07-17 14:02:52 -0700173 auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100174 if (outputThread == nullptr) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100175 ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
176 return;
177 }
178
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700179 for (const auto& device : patch.deviceStates) {
180 if (device.second) {
181 ++mActiveDevices[device.first];
182 ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
183 patch.streamHandle, device.first, mActiveDevices[device.first]);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100184
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700185 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
186 outputThread->startMelComputation_l(
187 mSoundDoseManager->getOrCreateProcessorForDevice(
188 device.first,
189 patch.streamHandle,
190 outputThread->sampleRate(),
191 outputThread->channelCount(),
192 outputThread->format()));
193 }
194 }
195 }
196}
197
198void MelReporter::startMelComputationForDeviceId(audio_port_handle_t deviceId) {
199 ALOGV("%s(%d)", __func__, deviceId);
Andy Hung0169fbc2023-08-28 19:12:14 -0700200 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
201 audio_utils::lock_guard _l(mutex());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700202
203 for (auto& activeMelPatch : mActiveMelPatches) {
204 bool csdActive = false;
205 for (auto& device: activeMelPatch.second.deviceStates) {
206 if (device.first == deviceId && !device.second) {
207 device.second = true;
208 }
209 csdActive |= device.second;
210 }
211 if (csdActive && !activeMelPatch.second.csdActive) {
212 activeMelPatch.second.csdActive = csdActive;
213 startMelComputationForActivePatch_l(activeMelPatch.second);
Vlad Popa7e81cea2023-01-19 16:34:16 +0100214 }
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100215 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100216}
217
Andy Hungad2faf72023-07-13 20:00:50 -0700218void MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200219 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100220 ALOGV("%s csd is disabled", __func__);
221 return;
222 }
223
Vlad Popab042ee62022-10-20 18:05:00 +0200224 ActiveMelPatch melPatch;
225 {
Andy Hung0169fbc2023-08-28 19:12:14 -0700226 audio_utils::lock_guard _l(mutex());
Vlad Popab042ee62022-10-20 18:05:00 +0200227
228 auto patchIt = mActiveMelPatches.find(handle);
229 if (patchIt == mActiveMelPatches.end()) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100230 ALOGV("%s patch handle %d does not contain any mix sources with active MEL calculation",
231 __func__, handle);
Vlad Popab042ee62022-10-20 18:05:00 +0200232 return;
233 }
234
235 melPatch = patchIt->second;
236 mActiveMelPatches.erase(patchIt);
237 }
238
Andy Hung77448a52023-09-06 17:52:01 -0700239 audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hung0169fbc2023-08-28 19:12:14 -0700240 audio_utils::lock_guard _l(mutex());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700241 if (melPatch.csdActive) {
242 // only need to stop if patch was active
243 melPatch.csdActive = false;
244 stopMelComputationForPatch_l(melPatch);
245 }
Vlad Popab042ee62022-10-20 18:05:00 +0200246}
247
Andy Hungad2faf72023-07-13 20:00:50 -0700248void MelReporter::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
Andy Hung8e6b62a2023-07-13 18:11:33 -0700249 audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
François Gaffie58e73af2023-02-15 11:47:24 +0100250 onReleaseAudioPatch(oldHandle);
251 onCreateAudioPatch(newHandle, patch);
252}
253
Andy Hungad2faf72023-07-13 20:00:50 -0700254sp<media::ISoundDose> MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100255 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100256 // no need to lock since getSoundDoseInterface is synchronized
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100257 return mSoundDoseManager->getSoundDoseInterface(callback);
258}
259
Andy Hungad2faf72023-07-13 20:00:50 -0700260void MelReporter::stopInternalMelComputation() {
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100261 ALOGV("%s", __func__);
Andy Hung0169fbc2023-08-28 19:12:14 -0700262 audio_utils::lock_guard _l(mutex());
Vlad Popab1c53782023-08-21 19:52:14 -0700263 if (mUseHalSoundDoseInterface) {
264 return;
265 }
Vlad Popa870f6d62022-12-22 12:15:47 +0100266 mActiveMelPatches.clear();
267 mUseHalSoundDoseInterface = true;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100268}
269
Andy Hungad2faf72023-07-13 20:00:50 -0700270void MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
Andy Hung920f6572022-10-06 12:09:49 -0700271NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
272{
Andy Hungb60a2c82023-07-17 14:02:52 -0700273 auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100274
Vlad Popa7e81cea2023-01-19 16:34:16 +0100275 ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700276 for (const auto& device : patch.deviceStates) {
277 if (mActiveDevices[device.first] > 0) {
278 --mActiveDevices[device.first];
279 if (mActiveDevices[device.first] == 0) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100280 // no stream is using deviceId anymore
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700281 ALOGI("%s removing device %d from active CSD devices", __func__, device.first);
282 mSoundDoseManager->clearMapDeviceIdEntries(device.first);
Vlad Popa7e81cea2023-01-19 16:34:16 +0100283 }
284 }
285 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100286
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700287 mSoundDoseManager->removeStreamProcessor(patch.streamHandle);
Vlad Popa69fbbee2023-04-25 12:23:24 +0200288 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100289 outputThread->stopMelComputation_l();
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100290 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100291}
292
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700293void MelReporter::stopMelComputationForDeviceId(audio_port_handle_t deviceId) {
294 ALOGV("%s(%d)", __func__, deviceId);
Andy Hung0169fbc2023-08-28 19:12:14 -0700295 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
296 audio_utils::lock_guard _l(mutex());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700297
298 for (auto& activeMelPatch : mActiveMelPatches) {
299 bool csdActive = false;
300 for (auto& device: activeMelPatch.second.deviceStates) {
301 if (device.first == deviceId && device.second) {
302 device.second = false;
303 }
304 csdActive |= device.second;
305 }
306
307 if (!csdActive && activeMelPatch.second.csdActive) {
308 activeMelPatch.second.csdActive = csdActive;
309 stopMelComputationForPatch_l(activeMelPatch.second);
310 }
311 }
312
313}
Vlad Popa7e81cea2023-01-19 16:34:16 +0100314
Vlad Popa1c67ad62024-01-19 17:53:42 -0800315void MelReporter::applyAllAudioPatches() {
316 ALOGV("%s", __func__);
317
318 std::vector<IAfPatchPanel::Patch> patchesCopy;
319 {
320 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
321 for (const auto& patch : mAfPatchPanel->patches_l()) {
322 patchesCopy.emplace_back(patch.second);
323 }
324 }
325
326 for (const auto& patch : patchesCopy) {
327 onCreateAudioPatch(patch.mHalHandle, patch);
328 }
329}
330
Andy Hungad2faf72023-07-13 20:00:50 -0700331std::optional<audio_patch_handle_t> MelReporter::activePatchStreamHandle_l(
Vlad Popa7e81cea2023-01-19 16:34:16 +0100332 audio_io_handle_t streamHandle) {
333 for(const auto& patchIt : mActiveMelPatches) {
334 if (patchIt.second.streamHandle == streamHandle) {
335 return patchIt.first;
336 }
337 }
338 return std::nullopt;
339}
340
Andy Hungad2faf72023-07-13 20:00:50 -0700341bool MelReporter::useHalSoundDoseInterface_l() {
Vlad Popaeb8036a2023-09-29 18:20:04 -0700342 return !mSoundDoseManager->isFrameworkMelForced() & mUseHalSoundDoseInterface;
Vlad Popa7e81cea2023-01-19 16:34:16 +0100343}
344
Andy Hungad2faf72023-07-13 20:00:50 -0700345std::string MelReporter::dump() {
Andy Hung0169fbc2023-08-28 19:12:14 -0700346 audio_utils::lock_guard _l(mutex());
Vlad Popa2900c0a2022-10-24 13:38:00 +0200347 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100348 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200349 return output;
350}
351
352} // namespace android