blob: ef932ece8bce8b2e1d5aa0c63989588a08a11dc1 [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 Hung81ce7602023-07-13 20:00:50 -070019#define LOG_TAG "MelReporter"
Vlad Popab042ee62022-10-20 18:05:00 +020020
Andy Hung4f274952023-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 Hung81ce7602023-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) {
Vlad Popa63c48dd2023-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 Popa63c48dd2023-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 Popa63c48dd2023-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 Hung81ce7602023-07-13 20:00:50 -070063void MelReporter::activateInternalSoundDoseComputation() {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010064 {
Andy Hungd65f1d82023-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 Popa63c48dd2023-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 Hung81ce7602023-07-13 20:00:50 -070077void MelReporter::onFirstRef() {
Andy Hungf9e248b2023-07-17 14:02:52 -070078 mAfMelReporterCallback->getPatchCommandThread()->addListener(this);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010079
Vlad Popa197faf82023-07-27 18:27:59 -070080 mSoundDoseManager = sp<SoundDoseManager>::make(sp<IMelReporterCallback>::fromExisting(this));
Vlad Popab042ee62022-10-20 18:05:00 +020081}
82
Andy Hung81ce7602023-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 Hungcd88bfe2023-09-06 17:52:01 -070090 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hungd65f1d82023-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 Popa197faf82023-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 Hung81ce7602023-07-13 20:00:50 -0700120void MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
Andy Hungc0ab56b2023-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 Popa197faf82023-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 Popa197faf82023-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 Popa197faf82023-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 Popa197faf82023-07-27 18:27:59 -0700156 if (!newPatch.deviceStates.empty() && newPatch.csdActive) {
Andy Hungcd88bfe2023-09-06 17:52:01 -0700157 audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hungd65f1d82023-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 Hung81ce7602023-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 Hungf9e248b2023-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 Popa197faf82023-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 Popa197faf82023-07-27 18:27:59 -0700180 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
181 outputThread->startMelComputation_l(
182 mSoundDoseManager->getOrCreateProcessorForDevice(
183 device.first,
184 patch.streamHandle,
Andy Hung0c1e11e2023-07-06 20:56:16 -0700185 outputThread->sampleRate(),
186 outputThread->channelCount(),
187 outputThread->format()));
Vlad Popa197faf82023-07-27 18:27:59 -0700188 }
189 }
190 }
191}
192
Andy Hung81ce7602023-07-13 20:00:50 -0700193void MelReporter::startMelComputationForDeviceId(audio_port_handle_t deviceId) {
Vlad Popa197faf82023-07-27 18:27:59 -0700194 ALOGV("%s(%d)", __func__, deviceId);
Andy Hungd65f1d82023-08-28 19:12:14 -0700195 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
196 audio_utils::lock_guard _l(mutex());
Vlad Popa197faf82023-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 Hung81ce7602023-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 Hungd65f1d82023-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 Hungcd88bfe2023-09-06 17:52:01 -0700234 audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex()); // AudioFlinger_Mutex
Andy Hungd65f1d82023-08-28 19:12:14 -0700235 audio_utils::lock_guard _l(mutex());
Andy Hung81ce7602023-07-13 20:00:50 -0700236 stopMelComputationForPatch_l(melPatch);
Vlad Popab042ee62022-10-20 18:05:00 +0200237}
238
Andy Hung81ce7602023-07-13 20:00:50 -0700239sp<media::ISoundDose> MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100240 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100241 // no need to lock since getSoundDoseInterface is synchronized
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100242 return mSoundDoseManager->getSoundDoseInterface(callback);
243}
244
Andy Hung81ce7602023-07-13 20:00:50 -0700245void MelReporter::stopInternalMelComputation() {
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100246 ALOGV("%s", __func__);
Andy Hungd65f1d82023-08-28 19:12:14 -0700247 audio_utils::lock_guard _l(mutex());
Vlad Popa63c48dd2023-08-21 19:52:14 -0700248 if (mUseHalSoundDoseInterface) {
249 return;
250 }
Vlad Popa870f6d62022-12-22 12:15:47 +0100251 mActiveMelPatches.clear();
252 mUseHalSoundDoseInterface = true;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100253}
254
Andy Hung81ce7602023-07-13 20:00:50 -0700255void MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
Andy Hung920f6572022-10-06 12:09:49 -0700256NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
257{
Andy Hungf9e248b2023-07-17 14:02:52 -0700258 auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100259
Vlad Popa7e81cea2023-01-19 16:34:16 +0100260 ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
Vlad Popa197faf82023-07-27 18:27:59 -0700261 for (const auto& device : patch.deviceStates) {
262 if (mActiveDevices[device.first] > 0) {
263 --mActiveDevices[device.first];
264 if (mActiveDevices[device.first] == 0) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100265 // no stream is using deviceId anymore
Vlad Popa197faf82023-07-27 18:27:59 -0700266 ALOGI("%s removing device %d from active CSD devices", __func__, device.first);
267 mSoundDoseManager->clearMapDeviceIdEntries(device.first);
Vlad Popa7e81cea2023-01-19 16:34:16 +0100268 }
269 }
270 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100271
Vlad Popa197faf82023-07-27 18:27:59 -0700272 mSoundDoseManager->removeStreamProcessor(patch.streamHandle);
Vlad Popa69fbbee2023-04-25 12:23:24 +0200273 if (outputThread != nullptr && !useHalSoundDoseInterface_l()) {
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100274 outputThread->stopMelComputation_l();
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100275 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100276}
277
Andy Hung81ce7602023-07-13 20:00:50 -0700278void MelReporter::stopMelComputationForDeviceId(audio_port_handle_t deviceId) {
Vlad Popa197faf82023-07-27 18:27:59 -0700279 ALOGV("%s(%d)", __func__, deviceId);
Andy Hungd65f1d82023-08-28 19:12:14 -0700280 audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());
281 audio_utils::lock_guard _l(mutex());
Vlad Popa197faf82023-07-27 18:27:59 -0700282
283 for (auto& activeMelPatch : mActiveMelPatches) {
284 bool csdActive = false;
285 for (auto& device: activeMelPatch.second.deviceStates) {
286 if (device.first == deviceId && device.second) {
287 device.second = false;
288 }
289 csdActive |= device.second;
290 }
291
292 if (!csdActive && activeMelPatch.second.csdActive) {
293 activeMelPatch.second.csdActive = csdActive;
294 stopMelComputationForPatch_l(activeMelPatch.second);
295 }
296 }
297
298}
Vlad Popa7e81cea2023-01-19 16:34:16 +0100299
Andy Hung81ce7602023-07-13 20:00:50 -0700300std::optional<audio_patch_handle_t> MelReporter::activePatchStreamHandle_l(
Vlad Popa7e81cea2023-01-19 16:34:16 +0100301 audio_io_handle_t streamHandle) {
302 for(const auto& patchIt : mActiveMelPatches) {
303 if (patchIt.second.streamHandle == streamHandle) {
304 return patchIt.first;
305 }
306 }
307 return std::nullopt;
308}
309
Andy Hung81ce7602023-07-13 20:00:50 -0700310bool MelReporter::useHalSoundDoseInterface_l() {
Vlad Popa69fbbee2023-04-25 12:23:24 +0200311 return !mSoundDoseManager->forceUseFrameworkMel() & mUseHalSoundDoseInterface;
Vlad Popa7e81cea2023-01-19 16:34:16 +0100312}
313
Andy Hung81ce7602023-07-13 20:00:50 -0700314std::string MelReporter::dump() {
Andy Hungd65f1d82023-08-28 19:12:14 -0700315 audio_utils::lock_guard _l(mutex());
Vlad Popa2900c0a2022-10-24 13:38:00 +0200316 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100317 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200318 return output;
319}
320
321} // namespace android