blob: bc5b5dbef8654d575445a0d47dbfc3b229c4b4cd [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 Popa3d6d39d2022-12-21 18:59:16 +010084 if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
Vlad Popa91930462022-12-20 22:42:48 +010085 return true;
86 }
87
Vlad Popab042ee62022-10-20 18:05:00 +020088 switch (device) {
89 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
90 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
91 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
92 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
93 case AUDIO_DEVICE_OUT_HEARING_AID:
94 case AUDIO_DEVICE_OUT_USB_HEADSET:
95 case AUDIO_DEVICE_OUT_BLE_HEADSET:
96 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
97 return true;
98 default:
99 return false;
100 }
101}
102
103void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
104 const PatchPanel::Patch& patch) {
105 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
106 __func__, handle, patch.mHalHandle,
107 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
108 if (patch.mAudioPatch.num_sources == 0
109 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
110 ALOGW("%s: patch does not contain any mix sources", __func__);
111 return;
112 }
113
114 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
115 ActiveMelPatch newPatch;
116 newPatch.streamHandle = streamHandle;
117 for (int i = 0; i < patch.mAudioPatch.num_sinks; ++ i) {
118 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
119 && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
120 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
121 newPatch.deviceHandles.push_back(deviceId);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100122 AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
123 patch.mAudioPatch.sinks[i].ext.device.address};
124 mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200125
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100126 bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100127 {
128 std::lock_guard _l(mLock);
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100129 useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100130 }
131 if (!useHalSoundDoseInterface) {
132 startMelComputationForNewPatch(streamHandle, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200133 }
134 }
135 }
136
137 std::lock_guard _l(mLock);
138 mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
139}
140
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100141void AudioFlinger::MelReporter::startMelComputationForNewPatch(
142 audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
143 // Start the MEL calculation in the PlaybackThread
144 std::lock_guard _lAf(mAudioFlinger.mLock);
145 auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
146 if (thread != nullptr) {
147 thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
148 deviceId,
149 streamHandle,
150 thread->mSampleRate,
151 thread->mChannelCount,
152 thread->mFormat));
153 }
154}
155
Vlad Popab042ee62022-10-20 18:05:00 +0200156void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
157 ALOGV("%s", __func__);
158
159 ActiveMelPatch melPatch;
160 {
161 std::lock_guard _l(mLock);
162
163 auto patchIt = mActiveMelPatches.find(handle);
164 if (patchIt == mActiveMelPatches.end()) {
165 ALOGW(
166 "%s patch does not contain any mix sources with active MEL calculation",
167 __func__);
168 return;
169 }
170
171 melPatch = patchIt->second;
172 mActiveMelPatches.erase(patchIt);
173 }
174
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100175 for (const auto& deviceId : melPatch.deviceHandles) {
176 mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200177 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100178 stopInternalMelComputationForStream(melPatch.streamHandle);
Vlad Popab042ee62022-10-20 18:05:00 +0200179}
180
Vlad Popae3fd1c22022-11-07 21:03:18 +0100181sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100182 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100183 // no need to lock since getSoundDoseInterface is synchronized
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100184 return mSoundDoseManager->getSoundDoseInterface(callback);
185}
186
187void AudioFlinger::MelReporter::stopInternalMelComputation() {
188 ALOGV("%s", __func__);
Vlad Popa870f6d62022-12-22 12:15:47 +0100189 std::lock_guard _l(mLock);
190 mActiveMelPatches.clear();
191 mUseHalSoundDoseInterface = true;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100192}
193
194void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
195 ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
196
197 std::lock_guard _lAf(mAudioFlinger.mLock);
198 mSoundDoseManager->removeStreamProcessor(streamId);
199 auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
200 if (thread != nullptr) {
201 thread->stopMelComputation();
202 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100203}
204
Vlad Popab042ee62022-10-20 18:05:00 +0200205std::string AudioFlinger::MelReporter::dump() {
206 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200207 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100208 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200209 return output;
210}
211
212} // namespace android