blob: b1859597ff90eaf89e0916b276eb32207b0acbe8 [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>
Vlad Popa1d5f0d52022-12-18 12:21:26 +010025#include <android/binder_manager.h>
Vlad Popa2900c0a2022-10-24 13:38:00 +020026#include <utils/Log.h>
27
Vlad Popa1d5f0d52022-12-18 12:21:26 +010028using aidl::android::hardware::audio::core::ISoundDose;
29using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
30
Vlad Popab042ee62022-10-20 18:05:00 +020031namespace android {
32
Vlad Popa1d5f0d52022-12-18 12:21:26 +010033constexpr std::string_view kSoundDoseInterfaceModule = "/default";
34
35bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010036 if (mSoundDoseManager->forceUseFrameworkMel()) {
37 ALOGD("%s: Forcing use of internal MEL computation.", __func__);
38 activateInternalSoundDoseComputation();
39 return false;
40 }
41
Vlad Popa1d5f0d52022-12-18 12:21:26 +010042 if (mSoundDoseFactory == nullptr) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010043 ALOGW("%s: sound dose HAL reporting not available", __func__);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010044 activateInternalSoundDoseComputation();
45 return false;
46 }
47
48 std::shared_ptr<ISoundDose> soundDoseInterface;
49 auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface);
50 if (!result.isOk()) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010051 ALOGW("%s: HAL cannot provide sound dose interface for module %s",
Vlad Popa1d5f0d52022-12-18 12:21:26 +010052 __func__, module.c_str());
53 activateInternalSoundDoseComputation();
54 return false;
55 }
56
57 if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010058 ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +010059 activateInternalSoundDoseComputation();
60 return false;
61 }
62
63 std::lock_guard _l(mLock);
64 mUseHalSoundDoseInterface = true;
65 stopInternalMelComputation();
66 return true;
67}
68
69void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
Vlad Popa3d6d39d2022-12-21 18:59:16 +010070 {
71 std::lock_guard _l(mLock);
72 if (!mUseHalSoundDoseInterface) {
73 // no need to start internal MEL on active patches
74 return;
75 }
76 mUseHalSoundDoseInterface = false;
77 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +010078
Vlad Popa3d6d39d2022-12-21 18:59:16 +010079 mSoundDoseManager->setHalSoundDoseInterface(nullptr);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010080
81 for (const auto& activePatches : mActiveMelPatches) {
82 for (const auto& deviceId : activePatches.second.deviceHandles) {
83 startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId);
84 }
85 }
86}
87
88void AudioFlinger::MelReporter::onFirstRef() {
89 mAudioFlinger.mPatchCommandThread->addListener(this);
90
91 std::string interface =
92 std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data();
93 AIBinder* binder = AServiceManager_checkService(interface.c_str());
94 if (binder == nullptr) {
95 ALOGW("%s service %s doesn't exist", __func__, interface.c_str());
96 return;
97 }
98
99 mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder));
100}
101
Vlad Popab042ee62022-10-20 18:05:00 +0200102bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100103 if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
Vlad Popa91930462022-12-20 22:42:48 +0100104 return true;
105 }
106
Vlad Popab042ee62022-10-20 18:05:00 +0200107 switch (device) {
108 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
109 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
110 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
111 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
112 case AUDIO_DEVICE_OUT_HEARING_AID:
113 case AUDIO_DEVICE_OUT_USB_HEADSET:
114 case AUDIO_DEVICE_OUT_BLE_HEADSET:
115 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
116 return true;
117 default:
118 return false;
119 }
120}
121
122void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
123 const PatchPanel::Patch& patch) {
124 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
125 __func__, handle, patch.mHalHandle,
126 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
127 if (patch.mAudioPatch.num_sources == 0
128 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
129 ALOGW("%s: patch does not contain any mix sources", __func__);
130 return;
131 }
132
133 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
134 ActiveMelPatch newPatch;
135 newPatch.streamHandle = streamHandle;
136 for (int i = 0; i < patch.mAudioPatch.num_sinks; ++ i) {
137 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
138 && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
139 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
140 newPatch.deviceHandles.push_back(deviceId);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100141 AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
142 patch.mAudioPatch.sinks[i].ext.device.address};
143 mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200144
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100145 bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100146 {
147 std::lock_guard _l(mLock);
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100148 useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100149 }
150 if (!useHalSoundDoseInterface) {
151 startMelComputationForNewPatch(streamHandle, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200152 }
153 }
154 }
155
156 std::lock_guard _l(mLock);
157 mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
158}
159
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100160void AudioFlinger::MelReporter::startMelComputationForNewPatch(
161 audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
162 // Start the MEL calculation in the PlaybackThread
163 std::lock_guard _lAf(mAudioFlinger.mLock);
164 auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
165 if (thread != nullptr) {
166 thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
167 deviceId,
168 streamHandle,
169 thread->mSampleRate,
170 thread->mChannelCount,
171 thread->mFormat));
172 }
173}
174
Vlad Popab042ee62022-10-20 18:05:00 +0200175void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
176 ALOGV("%s", __func__);
177
178 ActiveMelPatch melPatch;
179 {
180 std::lock_guard _l(mLock);
181
182 auto patchIt = mActiveMelPatches.find(handle);
183 if (patchIt == mActiveMelPatches.end()) {
184 ALOGW(
185 "%s patch does not contain any mix sources with active MEL calculation",
186 __func__);
187 return;
188 }
189
190 melPatch = patchIt->second;
191 mActiveMelPatches.erase(patchIt);
192 }
193
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100194 for (const auto& deviceId : melPatch.deviceHandles) {
195 mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200196 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100197 stopInternalMelComputationForStream(melPatch.streamHandle);
Vlad Popab042ee62022-10-20 18:05:00 +0200198}
199
Vlad Popae3fd1c22022-11-07 21:03:18 +0100200sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100201 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100202 // no need to lock since getSoundDoseInterface is synchronized
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100203 return mSoundDoseManager->getSoundDoseInterface(callback);
204}
205
206void AudioFlinger::MelReporter::stopInternalMelComputation() {
207 ALOGV("%s", __func__);
208 std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy;
209 {
210 std::lock_guard _l(mLock);
211 activePatchesCopy = mActiveMelPatches;
212 mActiveMelPatches.clear();
213 }
214
215 for (const auto& activePatch : activePatchesCopy) {
216 stopInternalMelComputationForStream(activePatch.second.streamHandle);
217 }
218}
219
220void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
221 ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
222
223 std::lock_guard _lAf(mAudioFlinger.mLock);
224 mSoundDoseManager->removeStreamProcessor(streamId);
225 auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
226 if (thread != nullptr) {
227 thread->stopMelComputation();
228 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100229}
230
Vlad Popab042ee62022-10-20 18:05:00 +0200231std::string AudioFlinger::MelReporter::dump() {
232 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200233 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100234 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200235 return output;
236}
237
238} // namespace android