blob: 7902444985ec4ed7efc1a2432bfbb7d33cab8b7b [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) {
36 if (mSoundDoseFactory == nullptr) {
37 ALOGW("%s sound dose HAL reporting not available", __func__);
38 activateInternalSoundDoseComputation();
39 return false;
40 }
41
42 std::shared_ptr<ISoundDose> soundDoseInterface;
43 auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface);
44 if (!result.isOk()) {
45 ALOGW("%s HAL cannot provide sound dose interface for module %s",
46 __func__, module.c_str());
47 activateInternalSoundDoseComputation();
48 return false;
49 }
50
51 if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
52 ALOGW("%s cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
53 activateInternalSoundDoseComputation();
54 return false;
55 }
56
57 std::lock_guard _l(mLock);
58 mUseHalSoundDoseInterface = true;
59 stopInternalMelComputation();
60 return true;
61}
62
63void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
64 mSoundDoseManager->setHalSoundDoseInterface(nullptr);
65
66 std::lock_guard _l(mLock);
67 mUseHalSoundDoseInterface = false;
68
69 for (const auto& activePatches : mActiveMelPatches) {
70 for (const auto& deviceId : activePatches.second.deviceHandles) {
71 startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId);
72 }
73 }
74}
75
76void AudioFlinger::MelReporter::onFirstRef() {
77 mAudioFlinger.mPatchCommandThread->addListener(this);
78
79 std::string interface =
80 std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data();
81 AIBinder* binder = AServiceManager_checkService(interface.c_str());
82 if (binder == nullptr) {
83 ALOGW("%s service %s doesn't exist", __func__, interface.c_str());
84 return;
85 }
86
87 mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder));
88}
89
Vlad Popab042ee62022-10-20 18:05:00 +020090bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
Vlad Popa1d5f0d52022-12-18 12:21:26 +010091 if (mSoundDoseManager->computeCsdOnAllDevices()) {
Vlad Popa91930462022-12-20 22:42:48 +010092 return true;
93 }
94
Vlad Popab042ee62022-10-20 18:05:00 +020095 switch (device) {
96 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
97 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
98 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
99 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
100 case AUDIO_DEVICE_OUT_HEARING_AID:
101 case AUDIO_DEVICE_OUT_USB_HEADSET:
102 case AUDIO_DEVICE_OUT_BLE_HEADSET:
103 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
104 return true;
105 default:
106 return false;
107 }
108}
109
110void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
111 const PatchPanel::Patch& patch) {
112 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
113 __func__, handle, patch.mHalHandle,
114 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
115 if (patch.mAudioPatch.num_sources == 0
116 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
117 ALOGW("%s: patch does not contain any mix sources", __func__);
118 return;
119 }
120
121 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
122 ActiveMelPatch newPatch;
123 newPatch.streamHandle = streamHandle;
124 for (int i = 0; i < patch.mAudioPatch.num_sinks; ++ i) {
125 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
126 && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
127 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
128 newPatch.deviceHandles.push_back(deviceId);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100129 AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
130 patch.mAudioPatch.sinks[i].ext.device.address};
131 mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200132
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100133 bool useHalSoundDoseInterface;
134 {
135 std::lock_guard _l(mLock);
136 useHalSoundDoseInterface = mUseHalSoundDoseInterface;
137 }
138 if (!useHalSoundDoseInterface) {
139 startMelComputationForNewPatch(streamHandle, deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200140 }
141 }
142 }
143
144 std::lock_guard _l(mLock);
145 mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
146}
147
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100148void AudioFlinger::MelReporter::startMelComputationForNewPatch(
149 audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
150 // Start the MEL calculation in the PlaybackThread
151 std::lock_guard _lAf(mAudioFlinger.mLock);
152 auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
153 if (thread != nullptr) {
154 thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
155 deviceId,
156 streamHandle,
157 thread->mSampleRate,
158 thread->mChannelCount,
159 thread->mFormat));
160 }
161}
162
Vlad Popab042ee62022-10-20 18:05:00 +0200163void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
164 ALOGV("%s", __func__);
165
166 ActiveMelPatch melPatch;
167 {
168 std::lock_guard _l(mLock);
169
170 auto patchIt = mActiveMelPatches.find(handle);
171 if (patchIt == mActiveMelPatches.end()) {
172 ALOGW(
173 "%s patch does not contain any mix sources with active MEL calculation",
174 __func__);
175 return;
176 }
177
178 melPatch = patchIt->second;
179 mActiveMelPatches.erase(patchIt);
180 }
181
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100182 for (const auto& deviceId : melPatch.deviceHandles) {
183 mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
Vlad Popab042ee62022-10-20 18:05:00 +0200184 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100185 stopInternalMelComputationForStream(melPatch.streamHandle);
Vlad Popab042ee62022-10-20 18:05:00 +0200186}
187
Vlad Popae3fd1c22022-11-07 21:03:18 +0100188sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100189 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100190 // no need to lock since getSoundDoseInterface is synchronized
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100191 return mSoundDoseManager->getSoundDoseInterface(callback);
192}
193
194void AudioFlinger::MelReporter::stopInternalMelComputation() {
195 ALOGV("%s", __func__);
196 std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy;
197 {
198 std::lock_guard _l(mLock);
199 activePatchesCopy = mActiveMelPatches;
200 mActiveMelPatches.clear();
201 }
202
203 for (const auto& activePatch : activePatchesCopy) {
204 stopInternalMelComputationForStream(activePatch.second.streamHandle);
205 }
206}
207
208void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
209 ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
210
211 std::lock_guard _lAf(mAudioFlinger.mLock);
212 mSoundDoseManager->removeStreamProcessor(streamId);
213 auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
214 if (thread != nullptr) {
215 thread->stopMelComputation();
216 }
Vlad Popa63f047e2022-11-05 14:09:19 +0100217}
218
Vlad Popab042ee62022-10-20 18:05:00 +0200219std::string AudioFlinger::MelReporter::dump() {
220 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200221 std::string output("\nSound Dose:\n");
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100222 output.append(mSoundDoseManager->dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200223 return output;
224}
225
226} // namespace android