blob: 9fd2632e5d8f733fff86c0b159b21ad83d1ee88f [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
19#define LOG_TAG "AudioFlinger::MelReporter"
20
Vlad Popab042ee62022-10-20 18:05:00 +020021#include "AudioFlinger.h"
22
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
Vlad Popa03bd5bc2023-01-17 16:16:51 +010031bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module,
32 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
66void AudioFlinger::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
79void AudioFlinger::MelReporter::onFirstRef() {
80 mAudioFlinger.mPatchCommandThread->addListener(this);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010081}
82
Vlad Popab042ee62022-10-20 18:05:00 +020083bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
Vlad Popa617bbf02023-04-24 19:10:36 +020084 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +010085 ALOGV("%s csd is disabled", __func__);
86 return false;
87 }
Vlad Popa3d6d39d2022-12-21 18:59:16 +010088 if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
Vlad Popa91930462022-12-20 22:42:48 +010089 return true;
90 }
91
Vlad Popab042ee62022-10-20 18:05:00 +020092 switch (device) {
93 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
94 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
Vlad Popaa6316942023-04-14 18:16:18 +020095 // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets
96 // case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
Vlad Popab042ee62022-10-20 18:05:00 +020097 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
98 case AUDIO_DEVICE_OUT_HEARING_AID:
99 case AUDIO_DEVICE_OUT_USB_HEADSET:
100 case AUDIO_DEVICE_OUT_BLE_HEADSET:
101 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
102 return true;
103 default:
104 return false;
105 }
106}
107
Vlad Popa7e81cea2023-01-19 16:34:16 +0100108void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
109 const std::vector<playback_track_metadata_v7_t>& metadataVec) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200110 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100111 ALOGV("%s csd is disabled", __func__);
112 return;
113 }
114
Vlad Popa7e81cea2023-01-19 16:34:16 +0100115 std::lock_guard _laf(mAudioFlinger.mLock);
116 std::lock_guard _l(mLock);
117 auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
118 if (!activeMelPatchId) {
119 ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
120 return;
121 }
122
123 bool shouldActivateCsd = false;
124 for (const auto& metadata : metadataVec) {
125 if (metadata.base.usage == AUDIO_USAGE_GAME || metadata.base.usage == AUDIO_USAGE_MEDIA) {
126 shouldActivateCsd = true;
127 }
128 }
129
130 auto activeMelPatchIt = mActiveMelPatches.find(activeMelPatchId.value());
131 if (activeMelPatchIt != mActiveMelPatches.end()
132 && shouldActivateCsd != activeMelPatchIt->second.csdActive) {
133 if (activeMelPatchIt->second.csdActive) {
134 ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle);
135 stopMelComputationForPatch_l(activeMelPatchIt->second);
136 } else {
137 ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle);
138 startMelComputationForActivePatch_l(activeMelPatchIt->second);
139 }
140 activeMelPatchIt->second.csdActive = shouldActivateCsd;
141 }
142}
143
Vlad Popab042ee62022-10-20 18:05:00 +0200144void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
145 const PatchPanel::Patch& patch) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200146 if (!mSoundDoseManager->isCsdEnabled()) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100147 ALOGV("%s csd is disabled", __func__);
148 return;
149 }
Vlad Popa7e81cea2023-01-19 16:34:16 +0100150 if (useHalSoundDoseInterface()) {
151 ALOGV("%s using HAL sound dose, ignore new patch", __func__);
152 return;
153 }
154
Vlad Popab042ee62022-10-20 18:05:00 +0200155 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
156 __func__, handle, patch.mHalHandle,
157 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
158 if (patch.mAudioPatch.num_sources == 0
159 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100160 ALOGV("%s: patch does not contain any mix sources", __func__);
Vlad Popab042ee62022-10-20 18:05:00 +0200161 return;
162 }
163
164 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
165 ActiveMelPatch newPatch;
166 newPatch.streamHandle = streamHandle;
Andy Hung920f6572022-10-06 12:09:49 -0700167 for (size_t i = 0; i < patch.mAudioPatch.num_sinks; ++i) {
Vlad Popab042ee62022-10-20 18:05:00 +0200168 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
169 && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
170 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
171 newPatch.deviceHandles.push_back(deviceId);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100172 AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
173 patch.mAudioPatch.sinks[i].ext.device.address};
174 mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200175 }
176 }
177
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200178 if (!newPatch.deviceHandles.empty()) {
179 std::lock_guard _afl(mAudioFlinger.mLock);
180 std::lock_guard _l(mLock);
181 ALOGV("%s add patch handle %d to active devices", __func__, handle);
182 startMelComputationForActivePatch_l(newPatch);
183 newPatch.csdActive = true;
184 mActiveMelPatches[handle] = newPatch;
185 }
Vlad Popab042ee62022-10-20 18:05:00 +0200186}
187
Andy Hung920f6572022-10-06 12:09:49 -0700188void AudioFlinger::MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
189NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
190{
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100191 auto outputThread = mAudioFlinger.checkOutputThread_l(patch.streamHandle);
192 if (outputThread == nullptr) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100193 ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
194 return;
195 }
196
197 for (const auto& deviceHandle : patch.deviceHandles) {
198 ++mActiveDevices[deviceHandle];
199 ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__,
200 patch.streamHandle, deviceHandle, mActiveDevices[deviceHandle]);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100201
202 if (outputThread != nullptr) {
203 outputThread->startMelComputation_l(mSoundDoseManager->getOrCreateProcessorForDevice(
204 deviceHandle,
205 patch.streamHandle,
206 outputThread->mSampleRate,
207 outputThread->mChannelCount,
208 outputThread->mFormat));
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
Vlad Popab042ee62022-10-20 18:05:00 +0200213void AudioFlinger::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 {
221 std::lock_guard _l(mLock);
222
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
Vlad Popa7e81cea2023-01-19 16:34:16 +0100234 std::lock_guard _afl(mAudioFlinger.mLock);
235 std::lock_guard _l(mLock);
236 stopMelComputationForPatch_l(melPatch);
Vlad Popab042ee62022-10-20 18:05:00 +0200237}
238
Vlad Popae3fd1c22022-11-07 21:03:18 +0100239sp<media::ISoundDose> AudioFlinger::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
245void AudioFlinger::MelReporter::stopInternalMelComputation() {
246 ALOGV("%s", __func__);
Vlad Popa870f6d62022-12-22 12:15:47 +0100247 std::lock_guard _l(mLock);
248 mActiveMelPatches.clear();
249 mUseHalSoundDoseInterface = true;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100250}
251
Andy Hung920f6572022-10-06 12:09:49 -0700252void AudioFlinger::MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
253NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l
254{
Vlad Popaeafa0482023-02-23 14:35:56 +0100255 if (!patch.csdActive) {
256 // no need to stop CSD inactive patches
257 return;
258 }
259
Vlad Popa1c2f7e12023-03-28 02:08:56 +0200260 auto outputThread = mAudioFlinger.checkOutputThread_l(patch.streamHandle);
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100261
Vlad Popa7e81cea2023-01-19 16:34:16 +0100262 ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
263 for (const auto& deviceId : patch.deviceHandles) {
264 if (mActiveDevices[deviceId] > 0) {
265 --mActiveDevices[deviceId];
266 if (mActiveDevices[deviceId] == 0) {
267 // no stream is using deviceId anymore
268 ALOGI("%s removing device %d from active CSD devices", __func__, deviceId);
269 mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
270 }
271 }
272 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100273
Vlad Popa6fbbfbf2023-02-22 15:05:43 +0100274 if (outputThread != nullptr) {
275 outputThread->stopMelComputation_l();
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100276 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100277}
278
Vlad Popa7e81cea2023-01-19 16:34:16 +0100279
280std::optional<audio_patch_handle_t> AudioFlinger::MelReporter::activePatchStreamHandle_l(
281 audio_io_handle_t streamHandle) {
282 for(const auto& patchIt : mActiveMelPatches) {
283 if (patchIt.second.streamHandle == streamHandle) {
284 return patchIt.first;
285 }
286 }
287 return std::nullopt;
288}
289
290bool AudioFlinger::MelReporter::useHalSoundDoseInterface() {
291 bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
292 {
293 std::lock_guard _l(mLock);
294 useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
295 }
296 return useHalSoundDoseInterface;
297}
298
Vlad Popab042ee62022-10-20 18:05:00 +0200299std::string AudioFlinger::MelReporter::dump() {
300 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200301 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100302 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200303 return output;
304}
305
306} // namespace android