blob: 0ebb3eb434d2c3a06862ecfd9baad1b387d49363 [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 Popa3d6d39d2022-12-21 18:59:16 +010033 if (mSoundDoseManager->forceUseFrameworkMel()) {
34 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) {
41 ALOGW("%s: HAL cannot provide sound dose interface for module %s, use internal MEL",
Vlad Popa1d5f0d52022-12-18 12:21:26 +010042 __func__, module.c_str());
43 activateInternalSoundDoseComputation();
44 return false;
45 }
46
Vlad Popa03bd5bc2023-01-17 16:16:51 +010047 if (soundDoseBinder == nullptr) {
48 ALOGW("%s: HAL doesn't implement a sound dose interface for module %s, use internal MEL",
49 __func__, module.c_str());
50 activateInternalSoundDoseComputation();
51 return false;
52 }
53
54 std::shared_ptr<ISoundDose> soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder);
55
Vlad Popa1d5f0d52022-12-18 12:21:26 +010056 if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010057 ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +010058 activateInternalSoundDoseComputation();
59 return false;
60 }
61
Vlad Popa1d5f0d52022-12-18 12:21:26 +010062 stopInternalMelComputation();
63 return true;
64}
65
Andy Hungad2faf72023-07-13 20:00:50 -070066void MelReporter::activateInternalSoundDoseComputation() {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010067 {
68 std::lock_guard _l(mLock);
69 if (!mUseHalSoundDoseInterface) {
70 // no need to start internal MEL on active patches
71 return;
72 }
73 mUseHalSoundDoseInterface = false;
74 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +010075
Vlad Popa3d6d39d2022-12-21 18:59:16 +010076 mSoundDoseManager->setHalSoundDoseInterface(nullptr);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010077}
78
Andy Hungad2faf72023-07-13 20:00:50 -070079void MelReporter::onFirstRef() {
Andy Hungb60a2c82023-07-17 14:02:52 -070080 mAfMelReporterCallback->getPatchCommandThread()->addListener(this);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010081
Vlad Popaf79f6ba2023-07-27 18:27:59 -070082 mSoundDoseManager = sp<SoundDoseManager>::make(sp<IMelReporterCallback>::fromExisting(this));
Vlad Popab042ee62022-10-20 18:05:00 +020083}
84
Andy Hungad2faf72023-07-13 20:00:50 -070085void MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
Vlad Popa7e81cea2023-01-19 16:34:16 +010086 const std::vector<playback_track_metadata_v7_t>& metadataVec) {
Vlad Popa617bbf02023-04-24 19:10:36 +020087 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +010088 ALOGV("%s csd is disabled", __func__);
89 return;
90 }
91
Andy Hungb60a2c82023-07-17 14:02:52 -070092 std::lock_guard _laf(mAfMelReporterCallback->mutex());
Vlad Popa7e81cea2023-01-19 16:34:16 +010093 std::lock_guard _l(mLock);
94 auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
95 if (!activeMelPatchId) {
96 ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
97 return;
98 }
99
100 bool shouldActivateCsd = false;
101 for (const auto& metadata : metadataVec) {
102 if (metadata.base.usage == AUDIO_USAGE_GAME || metadata.base.usage == AUDIO_USAGE_MEDIA) {
103 shouldActivateCsd = true;
104 }
105 }
106
107 auto activeMelPatchIt = mActiveMelPatches.find(activeMelPatchId.value());
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700108 if (activeMelPatchIt != mActiveMelPatches.end()) {
109 if (shouldActivateCsd != activeMelPatchIt->second.csdActive) {
110 if (activeMelPatchIt->second.csdActive) {
111 ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle);
112 stopMelComputationForPatch_l(activeMelPatchIt->second);
113 } else {
114 ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle);
115 startMelComputationForActivePatch_l(activeMelPatchIt->second);
116 }
117 activeMelPatchIt->second.csdActive = shouldActivateCsd;
Vlad Popa7e81cea2023-01-19 16:34:16 +0100118 }
Vlad Popa7e81cea2023-01-19 16:34:16 +0100119 }
120}
121
Andy Hungad2faf72023-07-13 20:00:50 -0700122void MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
Andy Hung8e6b62a2023-07-13 18:11:33 -0700123 const IAfPatchPanel::Patch& patch) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200124 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100125 ALOGV("%s csd is disabled", __func__);
126 return;
127 }
Vlad Popa7e81cea2023-01-19 16:34:16 +0100128
Vlad Popab042ee62022-10-20 18:05:00 +0200129 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
130 __func__, handle, patch.mHalHandle,
131 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
132 if (patch.mAudioPatch.num_sources == 0
133 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100134 ALOGV("%s: patch does not contain any mix sources", __func__);
Vlad Popab042ee62022-10-20 18:05:00 +0200135 return;
136 }
137
138 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
139 ActiveMelPatch newPatch;
140 newPatch.streamHandle = streamHandle;
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700141 newPatch.csdActive = false;
Andy Hung920f6572022-10-06 12:09:49 -0700142 for (size_t i = 0; i < patch.mAudioPatch.num_sinks; ++i) {
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700143 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE &&
144 mSoundDoseManager->shouldComputeCsdForDeviceType(
145 patch.mAudioPatch.sinks[i].ext.device.type)) {
Vlad Popab042ee62022-10-20 18:05:00 +0200146 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700147 bool shouldComputeCsd = mSoundDoseManager->shouldComputeCsdForDeviceWithAddress(
148 patch.mAudioPatch.sinks[i].ext.device.type,
149 patch.mAudioPatch.sinks[i].ext.device.address);
150 newPatch.deviceStates.push_back({deviceId, shouldComputeCsd});
151 newPatch.csdActive |= shouldComputeCsd;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100152 AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
153 patch.mAudioPatch.sinks[i].ext.device.address};
154 mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200155 }
156 }
157
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700158 if (!newPatch.deviceStates.empty() && newPatch.csdActive) {
Andy Hungb60a2c82023-07-17 14:02:52 -0700159 std::lock_guard _afl(mAfMelReporterCallback->mutex());
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200160 std::lock_guard _l(mLock);
161 ALOGV("%s add patch handle %d to active devices", __func__, handle);
162 startMelComputationForActivePatch_l(newPatch);
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200163 mActiveMelPatches[handle] = newPatch;
164 }
Vlad Popab042ee62022-10-20 18:05:00 +0200165}
166
Andy Hungad2faf72023-07-13 20:00:50 -0700167void MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
Andy Hung920f6572022-10-06 12:09:49 -0700168NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
169{
Andy Hungb60a2c82023-07-17 14:02:52 -0700170 auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100171 if (outputThread == nullptr) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100172 ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
173 return;
174 }
175
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700176 for (const auto& device : patch.deviceStates) {
177 if (device.second) {
178 ++mActiveDevices[device.first];
179 ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
180 patch.streamHandle, device.first, mActiveDevices[device.first]);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100181
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700182 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
183 outputThread->startMelComputation_l(
184 mSoundDoseManager->getOrCreateProcessorForDevice(
185 device.first,
186 patch.streamHandle,
187 outputThread->sampleRate(),
188 outputThread->channelCount(),
189 outputThread->format()));
190 }
191 }
192 }
193}
194
195void MelReporter::startMelComputationForDeviceId(audio_port_handle_t deviceId) {
196 ALOGV("%s(%d)", __func__, deviceId);
197 std::lock_guard _laf(mAfMelReporterCallback->mutex());
198 std::lock_guard _l(mLock);
199
200 for (auto& activeMelPatch : mActiveMelPatches) {
201 bool csdActive = false;
202 for (auto& device: activeMelPatch.second.deviceStates) {
203 if (device.first == deviceId && !device.second) {
204 device.second = true;
205 }
206 csdActive |= device.second;
207 }
208 if (csdActive && !activeMelPatch.second.csdActive) {
209 activeMelPatch.second.csdActive = csdActive;
210 startMelComputationForActivePatch_l(activeMelPatch.second);
Vlad Popa7e81cea2023-01-19 16:34:16 +0100211 }
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100212 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100213}
214
Andy Hungad2faf72023-07-13 20:00:50 -0700215void MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200216 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100217 ALOGV("%s csd is disabled", __func__);
218 return;
219 }
220
Vlad Popab042ee62022-10-20 18:05:00 +0200221 ActiveMelPatch melPatch;
222 {
223 std::lock_guard _l(mLock);
224
225 auto patchIt = mActiveMelPatches.find(handle);
226 if (patchIt == mActiveMelPatches.end()) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100227 ALOGV("%s patch handle %d does not contain any mix sources with active MEL calculation",
228 __func__, handle);
Vlad Popab042ee62022-10-20 18:05:00 +0200229 return;
230 }
231
232 melPatch = patchIt->second;
233 mActiveMelPatches.erase(patchIt);
234 }
235
Andy Hungb60a2c82023-07-17 14:02:52 -0700236 std::lock_guard _afl(mAfMelReporterCallback->mutex());
Vlad Popa7e81cea2023-01-19 16:34:16 +0100237 std::lock_guard _l(mLock);
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700238 if (melPatch.csdActive) {
239 // only need to stop if patch was active
240 melPatch.csdActive = false;
241 stopMelComputationForPatch_l(melPatch);
242 }
Vlad Popab042ee62022-10-20 18:05:00 +0200243}
244
Andy Hungad2faf72023-07-13 20:00:50 -0700245void MelReporter::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
Andy Hung8e6b62a2023-07-13 18:11:33 -0700246 audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
François Gaffie58e73af2023-02-15 11:47:24 +0100247 onReleaseAudioPatch(oldHandle);
248 onCreateAudioPatch(newHandle, patch);
249}
250
Andy Hungad2faf72023-07-13 20:00:50 -0700251sp<media::ISoundDose> MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100252 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100253 // no need to lock since getSoundDoseInterface is synchronized
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100254 return mSoundDoseManager->getSoundDoseInterface(callback);
255}
256
Andy Hungad2faf72023-07-13 20:00:50 -0700257void MelReporter::stopInternalMelComputation() {
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100258 ALOGV("%s", __func__);
Vlad Popa870f6d62022-12-22 12:15:47 +0100259 std::lock_guard _l(mLock);
260 mActiveMelPatches.clear();
261 mUseHalSoundDoseInterface = true;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100262}
263
Andy Hungad2faf72023-07-13 20:00:50 -0700264void MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
Andy Hung920f6572022-10-06 12:09:49 -0700265NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
266{
Andy Hungb60a2c82023-07-17 14:02:52 -0700267 auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100268
Vlad Popa7e81cea2023-01-19 16:34:16 +0100269 ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700270 for (const auto& device : patch.deviceStates) {
271 if (mActiveDevices[device.first] > 0) {
272 --mActiveDevices[device.first];
273 if (mActiveDevices[device.first] == 0) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100274 // no stream is using deviceId anymore
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700275 ALOGI("%s removing device %d from active CSD devices", __func__, device.first);
276 mSoundDoseManager->clearMapDeviceIdEntries(device.first);
Vlad Popa7e81cea2023-01-19 16:34:16 +0100277 }
278 }
279 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100280
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700281 mSoundDoseManager->removeStreamProcessor(patch.streamHandle);
Vlad Popa69fbbee2023-04-25 12:23:24 +0200282 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100283 outputThread->stopMelComputation_l();
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100284 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100285}
286
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700287void MelReporter::stopMelComputationForDeviceId(audio_port_handle_t deviceId) {
288 ALOGV("%s(%d)", __func__, deviceId);
289 std::lock_guard _laf(mAfMelReporterCallback->mutex());
290 std::lock_guard _l(mLock);
291
292 for (auto& activeMelPatch : mActiveMelPatches) {
293 bool csdActive = false;
294 for (auto& device: activeMelPatch.second.deviceStates) {
295 if (device.first == deviceId && device.second) {
296 device.second = false;
297 }
298 csdActive |= device.second;
299 }
300
301 if (!csdActive && activeMelPatch.second.csdActive) {
302 activeMelPatch.second.csdActive = csdActive;
303 stopMelComputationForPatch_l(activeMelPatch.second);
304 }
305 }
306
307}
Vlad Popa7e81cea2023-01-19 16:34:16 +0100308
Andy Hungad2faf72023-07-13 20:00:50 -0700309std::optional<audio_patch_handle_t> MelReporter::activePatchStreamHandle_l(
Vlad Popa7e81cea2023-01-19 16:34:16 +0100310 audio_io_handle_t streamHandle) {
311 for(const auto& patchIt : mActiveMelPatches) {
312 if (patchIt.second.streamHandle == streamHandle) {
313 return patchIt.first;
314 }
315 }
316 return std::nullopt;
317}
318
Andy Hungad2faf72023-07-13 20:00:50 -0700319bool MelReporter::useHalSoundDoseInterface_l() {
Vlad Popa69fbbee2023-04-25 12:23:24 +0200320 return !mSoundDoseManager->forceUseFrameworkMel() & mUseHalSoundDoseInterface;
Vlad Popa7e81cea2023-01-19 16:34:16 +0100321}
322
Andy Hungad2faf72023-07-13 20:00:50 -0700323std::string MelReporter::dump() {
Vlad Popab042ee62022-10-20 18:05:00 +0200324 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200325 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100326 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200327 return output;
328}
329
330} // namespace android