blob: 92bf3b3939ed0b9ce8a2f668ba674bfb2893dc71 [file] [log] [blame]
Vlad Popa2900c0a2022-10-24 13:38: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 "SoundDoseManager"
20
21#include "SoundDoseManager.h"
22
Vlad Popa1d5f0d52022-12-18 12:21:26 +010023#include "android/media/SoundDoseRecord.h"
Vlad Popa2900c0a2022-10-24 13:38:00 +020024#include <android-base/stringprintf.h>
Vlad Popa1d5f0d52022-12-18 12:21:26 +010025#include <media/AidlConversionCppNdk.h>
26#include <cinttypes>
Vlad Popa4847de12023-03-16 18:30:08 +010027#include <ctime>
Vlad Popa4defd0b2022-11-06 14:22:31 +010028#include <utils/Log.h>
Vlad Popa2900c0a2022-10-24 13:38:00 +020029
30namespace android {
31
Vlad Popa1d5f0d52022-12-18 12:21:26 +010032using aidl::android::media::audio::common::AudioDevice;
Vlad Popa1d5f0d52022-12-18 12:21:26 +010033
Vlad Popa2900c0a2022-10-24 13:38:00 +020034namespace {
35
Vlad Popaeb8036a2023-09-29 18:20:04 -070036// Port handle used when CSD is computed on all devices. Should be a different value than
37// AUDIO_PORT_HANDLE_NONE which is associated with a sound dose callback failure
38constexpr audio_port_handle_t CSD_ON_ALL_DEVICES_PORT_HANDLE = -1;
39
Vlad Popa2900c0a2022-10-24 13:38:00 +020040int64_t getMonotonicSecond() {
41 struct timespec now_ts;
42 if (clock_gettime(CLOCK_MONOTONIC, &now_ts) != 0) {
43 ALOGE("%s: cannot get timestamp", __func__);
44 return -1;
45 }
46 return now_ts.tv_sec;
47}
48
49} // namespace
50
Vlad Popaf09e93f2022-10-31 16:27:12 +010051sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
Vlad Popa4defd0b2022-11-06 14:22:31 +010052 audio_port_handle_t deviceId, audio_io_handle_t streamHandle, uint32_t sampleRate,
53 size_t channelCount, audio_format_t format) {
Vlad Popaf2cf6742023-06-10 00:24:35 +020054 const std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +020055
Vlad Popab1c53782023-08-21 19:52:14 -070056 if (mHalSoundDose.size() > 0 && mEnabledCsd) {
Vlad Popa1c2f7e12023-03-28 02:08:56 +020057 ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
Vlad Popa1d5f0d52022-12-18 12:21:26 +010058 return nullptr;
59 }
60
Vlad Popaf09e93f2022-10-31 16:27:12 +010061 auto streamProcessor = mActiveProcessors.find(streamHandle);
Vlad Popa1c2f7e12023-03-28 02:08:56 +020062 if (streamProcessor != mActiveProcessors.end()) {
63 auto processor = streamProcessor->second.promote();
64 // if processor is nullptr it means it was removed by the playback
65 // thread and can be replaced in the mActiveProcessors map
66 if (processor != nullptr) {
67 ALOGV("%s: found callback for stream id %d", __func__, streamHandle);
68 const auto activeTypeIt = mActiveDeviceTypes.find(deviceId);
69 if (activeTypeIt != mActiveDeviceTypes.end()) {
70 processor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]);
71 }
72 processor->setDeviceId(deviceId);
73 processor->setOutputRs2UpperBound(mRs2UpperBound);
74 return processor;
Vlad Popa58e72dc2023-02-01 13:18:40 +010075 }
Vlad Popa2900c0a2022-10-24 13:38:00 +020076 }
Vlad Popa1c2f7e12023-03-28 02:08:56 +020077
78 ALOGV("%s: creating new callback for stream id %d", __func__, streamHandle);
79 sp<audio_utils::MelProcessor> melProcessor = sp<audio_utils::MelProcessor>::make(
80 sampleRate, channelCount, format, this, deviceId, mRs2UpperBound);
81 const auto activeTypeIt = mActiveDeviceTypes.find(deviceId);
82 if (activeTypeIt != mActiveDeviceTypes.end()) {
83 melProcessor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]);
84 }
85 mActiveProcessors[streamHandle] = melProcessor;
86 return melProcessor;
Vlad Popa2900c0a2022-10-24 13:38:00 +020087}
88
Vlad Popab1c53782023-08-21 19:52:14 -070089bool SoundDoseManager::setHalSoundDoseInterface(const std::string &module,
90 const std::shared_ptr<ISoundDose> &halSoundDose) {
Vlad Popa1d5f0d52022-12-18 12:21:26 +010091 ALOGV("%s", __func__);
92
Vlad Popab1c53782023-08-21 19:52:14 -070093 if (halSoundDose == nullptr) {
94 ALOGI("%s: passed ISoundDose object is null", __func__);
95 return false;
96 }
97
Vlad Popaf2cf6742023-06-10 00:24:35 +020098 std::shared_ptr<HalSoundDoseCallback> halSoundDoseCallback;
Vlad Popa1d5f0d52022-12-18 12:21:26 +010099 {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200100 const std::lock_guard _l(mLock);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100101
Vlad Popab1c53782023-08-21 19:52:14 -0700102 if (mHalSoundDose.find(module) != mHalSoundDose.end()) {
103 ALOGW("%s: Module %s already has a sound dose HAL assigned, skipping", __func__,
104 module.c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100105 return false;
106 }
Vlad Popab1c53782023-08-21 19:52:14 -0700107 mHalSoundDose[module] = halSoundDose;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100108
Vlad Popab1c53782023-08-21 19:52:14 -0700109 if (!halSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100110 ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
111 __func__,
Vlad Popa4847de12023-03-16 18:30:08 +0100112 mRs2UpperBound);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100113 }
114
115 // initialize the HAL sound dose callback lazily
116 if (mHalSoundDoseCallback == nullptr) {
117 mHalSoundDoseCallback =
118 ndk::SharedRefBase::make<HalSoundDoseCallback>(this);
119 }
Vlad Popaf2cf6742023-06-10 00:24:35 +0200120 halSoundDoseCallback = mHalSoundDoseCallback;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100121 }
122
Vlad Popaf2cf6742023-06-10 00:24:35 +0200123 auto status = halSoundDose->registerSoundDoseCallback(halSoundDoseCallback);
124
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100125 if (!status.isOk()) {
126 // Not a warning since this can happen if the callback was registered before
127 ALOGI("%s: Cannot register HAL sound dose callback with status message: %s",
128 __func__,
129 status.getMessage());
130 }
131
132 return true;
133}
134
Vlad Popab1c53782023-08-21 19:52:14 -0700135void SoundDoseManager::resetHalSoundDoseInterfaces() {
136 ALOGV("%s", __func__);
137
138 const std::lock_guard _l(mLock);
139 mHalSoundDose.clear();
140}
141
Vlad Popa4847de12023-03-16 18:30:08 +0100142void SoundDoseManager::setOutputRs2UpperBound(float rs2Value) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200143 ALOGV("%s", __func__);
Vlad Popaf2cf6742023-06-10 00:24:35 +0200144 const std::lock_guard _l(mLock);
Vlad Popaf09e93f2022-10-31 16:27:12 +0100145
Vlad Popab1c53782023-08-21 19:52:14 -0700146 if (mHalSoundDose.size() > 0) {
147 for (auto& halSoundDose : mHalSoundDose) {
148 // using the HAL sound dose interface
149 if (!halSoundDose.second->setOutputRs2UpperBound(rs2Value).isOk()) {
150 ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
151 continue;
152 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100153 }
Vlad Popab1c53782023-08-21 19:52:14 -0700154
Vlad Popa4847de12023-03-16 18:30:08 +0100155 mRs2UpperBound = rs2Value;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100156 return;
157 }
Vlad Popae3fd1c22022-11-07 21:03:18 +0100158
Vlad Popaf09e93f2022-10-31 16:27:12 +0100159 for (auto& streamProcessor : mActiveProcessors) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200160 const sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
Vlad Popaf09e93f2022-10-31 16:27:12 +0100161 if (processor != nullptr) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200162 const status_t result = processor->setOutputRs2UpperBound(rs2Value);
Vlad Popaf09e93f2022-10-31 16:27:12 +0100163 if (result != NO_ERROR) {
Vlad Popa4847de12023-03-16 18:30:08 +0100164 ALOGW("%s: could not set RS2 upper bound %f for stream %d", __func__, rs2Value,
Vlad Popaf09e93f2022-10-31 16:27:12 +0100165 streamProcessor.first);
Vlad Popa3c3995d2023-01-13 11:10:05 +0100166 return;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100167 }
Vlad Popa4847de12023-03-16 18:30:08 +0100168 mRs2UpperBound = rs2Value;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100169 }
170 }
171}
172
Vlad Popa4defd0b2022-11-06 14:22:31 +0100173void SoundDoseManager::removeStreamProcessor(audio_io_handle_t streamHandle) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200174 const std::lock_guard _l(mLock);
Vlad Popaf09e93f2022-10-31 16:27:12 +0100175 auto callbackToRemove = mActiveProcessors.find(streamHandle);
Vlad Popa4defd0b2022-11-06 14:22:31 +0100176 if (callbackToRemove != mActiveProcessors.end()) {
Vlad Popaf09e93f2022-10-31 16:27:12 +0100177 mActiveProcessors.erase(callbackToRemove);
178 }
179}
180
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100181audio_port_handle_t SoundDoseManager::getIdForAudioDevice(const AudioDevice& audioDevice) const {
Vlad Popaeb8036a2023-09-29 18:20:04 -0700182 if (isComputeCsdForcedOnAllDevices()) {
183 // If CSD is forced on all devices return random port id. Used only in testing.
184 // This is necessary since the patches that are registered before
185 // setComputeCsdOnAllDevices will not be contributing to mActiveDevices
186 return CSD_ON_ALL_DEVICES_PORT_HANDLE;
187 }
188
Vlad Popaf2cf6742023-06-10 00:24:35 +0200189 const std::lock_guard _l(mLock);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100190
191 audio_devices_t type;
192 std::string address;
193 auto result = aidl::android::aidl2legacy_AudioDevice_audio_device(
194 audioDevice, &type, &address);
195 if (result != NO_ERROR) {
196 ALOGE("%s: could not convert from AudioDevice to AudioDeviceTypeAddr", __func__);
197 return AUDIO_PORT_HANDLE_NONE;
198 }
199
200 auto adt = AudioDeviceTypeAddr(type, address);
201 auto deviceIt = mActiveDevices.find(adt);
202 if (deviceIt == mActiveDevices.end()) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100203 ALOGI("%s: could not find port id for device %s", __func__, adt.toString().c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100204 return AUDIO_PORT_HANDLE_NONE;
205 }
206 return deviceIt->second;
207}
208
209void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
210 const audio_port_handle_t deviceId) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200211 const std::lock_guard _l(mLock);
Vlad Popaeafa0482023-02-23 14:35:56 +0100212 ALOGI("%s: map address: %d to device id: %d", __func__, adt.mType, deviceId);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100213 mActiveDevices[adt] = deviceId;
Vlad Popa58e72dc2023-02-01 13:18:40 +0100214 mActiveDeviceTypes[deviceId] = adt.mType;
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100215}
216
217void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200218 const std::lock_guard _l(mLock);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100219 for (auto activeDevice = mActiveDevices.begin(); activeDevice != mActiveDevices.end();) {
220 if (activeDevice->second == deviceId) {
Vlad Popaeafa0482023-02-23 14:35:56 +0100221 ALOGI("%s: clear mapping type: %d to deviceId: %d",
222 __func__, activeDevice->first.mType, deviceId);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100223 activeDevice = mActiveDevices.erase(activeDevice);
224 continue;
225 }
226 ++activeDevice;
227 }
Vlad Popa58e72dc2023-02-01 13:18:40 +0100228 mActiveDeviceTypes.erase(deviceId);
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100229}
230
231ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
232 float in_currentDbA, const AudioDevice& in_audioDevice) {
Vlad Popab1c53782023-08-21 19:52:14 -0700233 sp<SoundDoseManager> soundDoseManager;
234 {
235 const std::lock_guard _l(mCbLock);
236 soundDoseManager = mSoundDoseManager.promote();
237 if (soundDoseManager == nullptr) {
238 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
239 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100240 }
241
Vlad Popab1c53782023-08-21 19:52:14 -0700242 if (!soundDoseManager->useHalSoundDose()) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100243 ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
244 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
245 }
246
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100247 auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
248 if (id == AUDIO_PORT_HANDLE_NONE) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100249 ALOGI("%s: no mapped id for audio device with type %d and address %s",
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100250 __func__, in_audioDevice.type.type,
Vlad Popa69fbbee2023-04-25 12:23:24 +0200251 in_audioDevice.address.toString().c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100252 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
253 }
254 soundDoseManager->onMomentaryExposure(in_currentDbA, id);
255
256 return ndk::ScopedAStatus::ok();
257}
258
259ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
260 const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
261 const AudioDevice& in_audioDevice) {
Vlad Popab1c53782023-08-21 19:52:14 -0700262 sp<SoundDoseManager> soundDoseManager;
263 {
264 const std::lock_guard _l(mCbLock);
265 soundDoseManager = mSoundDoseManager.promote();
266 if (soundDoseManager == nullptr) {
267 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
268 }
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100269 }
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100270
Vlad Popab1c53782023-08-21 19:52:14 -0700271 if (!soundDoseManager->useHalSoundDose()) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100272 ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
273 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
274 }
275
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100276 auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
277 if (id == AUDIO_PORT_HANDLE_NONE) {
Vlad Popa7e81cea2023-01-19 16:34:16 +0100278 ALOGI("%s: no mapped id for audio device with type %d and address %s",
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100279 __func__, in_audioDevice.type.type,
Vlad Popa69fbbee2023-04-25 12:23:24 +0200280 in_audioDevice.address.toString().c_str());
Vlad Popa1d5f0d52022-12-18 12:21:26 +0100281 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
282 }
283 // TODO: introduce timestamp in onNewMelValues callback
284 soundDoseManager->onNewMelValues(in_melRecord.melValues, 0,
285 in_melRecord.melValues.size(), id);
286
287 return ndk::ScopedAStatus::ok();
288}
289
Vlad Popae3fd1c22022-11-07 21:03:18 +0100290void SoundDoseManager::SoundDose::binderDied(__unused const wp<IBinder>& who) {
291 ALOGV("%s", __func__);
292
293 auto soundDoseManager = mSoundDoseManager.promote();
294 if (soundDoseManager != nullptr) {
295 soundDoseManager->resetSoundDose();
296 }
297}
298
Vlad Popa4847de12023-03-16 18:30:08 +0100299binder::Status SoundDoseManager::SoundDose::setOutputRs2UpperBound(float value) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100300 ALOGV("%s", __func__);
301 auto soundDoseManager = mSoundDoseManager.promote();
302 if (soundDoseManager != nullptr) {
Vlad Popa4847de12023-03-16 18:30:08 +0100303 soundDoseManager->setOutputRs2UpperBound(value);
Vlad Popae3fd1c22022-11-07 21:03:18 +0100304 }
305 return binder::Status::ok();
306}
307
308binder::Status SoundDoseManager::SoundDose::resetCsd(
309 float currentCsd, const std::vector<media::SoundDoseRecord>& records) {
310 ALOGV("%s", __func__);
311 auto soundDoseManager = mSoundDoseManager.promote();
312 if (soundDoseManager != nullptr) {
313 soundDoseManager->resetCsd(currentCsd, records);
314 }
315 return binder::Status::ok();
316}
317
Vlad Popa58e72dc2023-02-01 13:18:40 +0100318binder::Status SoundDoseManager::SoundDose::updateAttenuation(float attenuationDB, int device) {
319 ALOGV("%s", __func__);
320 auto soundDoseManager = mSoundDoseManager.promote();
321 if (soundDoseManager != nullptr) {
322 soundDoseManager->updateAttenuation(attenuationDB, static_cast<audio_devices_t>(device));
323 }
324 return binder::Status::ok();
325}
326
Vlad Popa617bbf02023-04-24 19:10:36 +0200327binder::Status SoundDoseManager::SoundDose::setCsdEnabled(bool enabled) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100328 ALOGV("%s", __func__);
329 auto soundDoseManager = mSoundDoseManager.promote();
330 if (soundDoseManager != nullptr) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200331 soundDoseManager->setCsdEnabled(enabled);
Vlad Popa2a06fca2023-02-06 16:45:45 +0100332 }
333 return binder::Status::ok();
334}
335
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700336binder::Status SoundDoseManager::SoundDose::initCachedAudioDeviceCategories(
337 const std::vector<media::ISoundDose::AudioDeviceCategory>& btDeviceCategories) {
338 ALOGV("%s", __func__);
339 auto soundDoseManager = mSoundDoseManager.promote();
340 if (soundDoseManager != nullptr) {
341 soundDoseManager->initCachedAudioDeviceCategories(btDeviceCategories);
342 }
343 return binder::Status::ok();
344}
345binder::Status SoundDoseManager::SoundDose::setAudioDeviceCategory(
346 const media::ISoundDose::AudioDeviceCategory& btAudioDevice) {
347 ALOGV("%s", __func__);
348 auto soundDoseManager = mSoundDoseManager.promote();
349 if (soundDoseManager != nullptr) {
350 soundDoseManager->setAudioDeviceCategory(btAudioDevice);
351 }
352 return binder::Status::ok();
353}
354
Vlad Popa4847de12023-03-16 18:30:08 +0100355binder::Status SoundDoseManager::SoundDose::getOutputRs2UpperBound(float* value) {
Vlad Popa91930462022-12-20 22:42:48 +0100356 ALOGV("%s", __func__);
357 auto soundDoseManager = mSoundDoseManager.promote();
358 if (soundDoseManager != nullptr) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200359 const std::lock_guard _l(soundDoseManager->mLock);
Vlad Popa4847de12023-03-16 18:30:08 +0100360 *value = soundDoseManager->mRs2UpperBound;
Vlad Popa91930462022-12-20 22:42:48 +0100361 }
362 return binder::Status::ok();
363}
364
365binder::Status SoundDoseManager::SoundDose::getCsd(float* value) {
366 ALOGV("%s", __func__);
367 auto soundDoseManager = mSoundDoseManager.promote();
368 if (soundDoseManager != nullptr) {
369 *value = soundDoseManager->mMelAggregator->getCsd();
370 }
371 return binder::Status::ok();
372}
373
374binder::Status SoundDoseManager::SoundDose::forceUseFrameworkMel(bool useFrameworkMel) {
375 ALOGV("%s", __func__);
376 auto soundDoseManager = mSoundDoseManager.promote();
377 if (soundDoseManager != nullptr) {
378 soundDoseManager->setUseFrameworkMel(useFrameworkMel);
379 }
380 return binder::Status::ok();
381}
382
383binder::Status SoundDoseManager::SoundDose::forceComputeCsdOnAllDevices(
384 bool computeCsdOnAllDevices) {
385 ALOGV("%s", __func__);
386 auto soundDoseManager = mSoundDoseManager.promote();
387 if (soundDoseManager != nullptr) {
388 soundDoseManager->setComputeCsdOnAllDevices(computeCsdOnAllDevices);
389 }
390 return binder::Status::ok();
391}
392
Vlad Popa95ee3ca2023-03-20 19:29:38 +0000393binder::Status SoundDoseManager::SoundDose::isSoundDoseHalSupported(bool* value) {
394 ALOGV("%s", __func__);
395 *value = false;
396 auto soundDoseManager = mSoundDoseManager.promote();
397 if (soundDoseManager != nullptr) {
398 *value = soundDoseManager->isSoundDoseHalSupported();
399 }
400 return binder::Status::ok();
401}
402
Vlad Popa58e72dc2023-02-01 13:18:40 +0100403void SoundDoseManager::updateAttenuation(float attenuationDB, audio_devices_t deviceType) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200404 const std::lock_guard _l(mLock);
Vlad Popaeafa0482023-02-23 14:35:56 +0100405 ALOGV("%s: updating MEL processor attenuation for device type %d to %f",
Vlad Popa58e72dc2023-02-01 13:18:40 +0100406 __func__, deviceType, attenuationDB);
407 mMelAttenuationDB[deviceType] = attenuationDB;
408 for (const auto& mp : mActiveProcessors) {
409 auto melProcessor = mp.second.promote();
410 if (melProcessor != nullptr) {
411 auto deviceId = melProcessor->getDeviceId();
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700412 const auto deviceTypeIt = mActiveDeviceTypes.find(deviceId);
413 if (deviceTypeIt != mActiveDeviceTypes.end() &&
414 deviceTypeIt->second == deviceType) {
Vlad Popaeafa0482023-02-23 14:35:56 +0100415 ALOGV("%s: set attenuation for deviceId %d to %f",
Vlad Popa58e72dc2023-02-01 13:18:40 +0100416 __func__, deviceId, attenuationDB);
417 melProcessor->setAttenuation(attenuationDB);
418 }
419 }
420 }
421}
422
Vlad Popa617bbf02023-04-24 19:10:36 +0200423void SoundDoseManager::setCsdEnabled(bool enabled) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100424 ALOGV("%s", __func__);
425
Vlad Popaf2cf6742023-06-10 00:24:35 +0200426 const std::lock_guard _l(mLock);
Vlad Popa617bbf02023-04-24 19:10:36 +0200427 mEnabledCsd = enabled;
Vlad Popa2a06fca2023-02-06 16:45:45 +0100428
Vlad Popa2a06fca2023-02-06 16:45:45 +0100429 for (auto& activeEntry : mActiveProcessors) {
430 auto melProcessor = activeEntry.second.promote();
431 if (melProcessor != nullptr) {
Vlad Popa617bbf02023-04-24 19:10:36 +0200432 if (enabled) {
433 melProcessor->resume();
434 } else {
435 melProcessor->pause();
436 }
Vlad Popa2a06fca2023-02-06 16:45:45 +0100437 }
438 }
439}
440
Vlad Popa617bbf02023-04-24 19:10:36 +0200441bool SoundDoseManager::isCsdEnabled() {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200442 const std::lock_guard _l(mLock);
Vlad Popa617bbf02023-04-24 19:10:36 +0200443 return mEnabledCsd;
Vlad Popa2a06fca2023-02-06 16:45:45 +0100444}
445
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700446void SoundDoseManager::initCachedAudioDeviceCategories(
447 const std::vector<media::ISoundDose::AudioDeviceCategory>& deviceCategories) {
448 ALOGV("%s", __func__);
449 {
450 const std::lock_guard _l(mLock);
451 mBluetoothDevicesWithCsd.clear();
452 }
453 for (const auto& btDeviceCategory : deviceCategories) {
454 setAudioDeviceCategory(btDeviceCategory);
455 }
456}
457
458void SoundDoseManager::setAudioDeviceCategory(
459 const media::ISoundDose::AudioDeviceCategory& audioDevice) {
460 ALOGV("%s: set BT audio device type with address %s to headphone %d", __func__,
461 audioDevice.address.c_str(), audioDevice.csdCompatible);
462
463 std::vector<audio_port_handle_t> devicesToStart;
464 std::vector<audio_port_handle_t> devicesToStop;
465 {
466 const std::lock_guard _l(mLock);
467 const auto deviceIt = mBluetoothDevicesWithCsd.find(
468 std::make_pair(audioDevice.address,
469 static_cast<audio_devices_t>(audioDevice.internalAudioType)));
470 if (deviceIt != mBluetoothDevicesWithCsd.end()) {
471 deviceIt->second = audioDevice.csdCompatible;
472 } else {
473 mBluetoothDevicesWithCsd.emplace(
474 std::make_pair(audioDevice.address,
475 static_cast<audio_devices_t>(audioDevice.internalAudioType)),
476 audioDevice.csdCompatible);
477 }
478
479 for (const auto &activeDevice: mActiveDevices) {
480 if (activeDevice.first.address() == audioDevice.address &&
481 activeDevice.first.mType ==
482 static_cast<audio_devices_t>(audioDevice.internalAudioType)) {
483 if (audioDevice.csdCompatible) {
484 devicesToStart.push_back(activeDevice.second);
485 } else {
486 devicesToStop.push_back(activeDevice.second);
487 }
488 }
489 }
490 }
491
492 for (const auto& deviceToStart : devicesToStart) {
493 mMelReporterCallback->startMelComputationForDeviceId(deviceToStart);
494 }
495 for (const auto& deviceToStop : devicesToStop) {
496 mMelReporterCallback->stopMelComputationForDeviceId(deviceToStop);
497 }
498}
499
500bool SoundDoseManager::shouldComputeCsdForDeviceType(audio_devices_t device) {
501 if (!isCsdEnabled()) {
502 ALOGV("%s csd is disabled", __func__);
503 return false;
504 }
Vlad Popaeb8036a2023-09-29 18:20:04 -0700505 if (isComputeCsdForcedOnAllDevices()) {
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700506 return true;
507 }
508
509 switch (device) {
510 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
511 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
Vlad Popaa9f6b862023-07-31 17:33:25 -0700512 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700513 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
514 case AUDIO_DEVICE_OUT_USB_HEADSET:
515 case AUDIO_DEVICE_OUT_BLE_HEADSET:
516 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
517 return true;
518 default:
519 return false;
520 }
521}
522
523bool SoundDoseManager::shouldComputeCsdForDeviceWithAddress(const audio_devices_t type,
524 const std::string& deviceAddress) {
525 if (!isCsdEnabled()) {
526 ALOGV("%s csd is disabled", __func__);
527 return false;
528 }
Vlad Popaeb8036a2023-09-29 18:20:04 -0700529 if (isComputeCsdForcedOnAllDevices()) {
Vlad Popaf79f6ba2023-07-27 18:27:59 -0700530 return true;
531 }
532
533 if (!audio_is_ble_out_device(type) && !audio_is_a2dp_device(type)) {
534 return shouldComputeCsdForDeviceType(type);
535 }
536
537 const std::lock_guard _l(mLock);
538 const auto deviceIt = mBluetoothDevicesWithCsd.find(std::make_pair(deviceAddress, type));
539 return deviceIt != mBluetoothDevicesWithCsd.end() && deviceIt->second;
540}
541
Vlad Popa91930462022-12-20 22:42:48 +0100542void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100543 // invalidate any HAL sound dose interface used
Vlad Popab1c53782023-08-21 19:52:14 -0700544 resetHalSoundDoseInterfaces();
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100545
Vlad Popaf2cf6742023-06-10 00:24:35 +0200546 const std::lock_guard _l(mLock);
Vlad Popa91930462022-12-20 22:42:48 +0100547 mUseFrameworkMel = useFrameworkMel;
548}
549
Vlad Popaeb8036a2023-09-29 18:20:04 -0700550bool SoundDoseManager::isFrameworkMelForced() const {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200551 const std::lock_guard _l(mLock);
Vlad Popa91930462022-12-20 22:42:48 +0100552 return mUseFrameworkMel;
553}
554
555void SoundDoseManager::setComputeCsdOnAllDevices(bool computeCsdOnAllDevices) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200556 const std::lock_guard _l(mLock);
Vlad Popa91930462022-12-20 22:42:48 +0100557 mComputeCsdOnAllDevices = computeCsdOnAllDevices;
558}
559
Vlad Popaeb8036a2023-09-29 18:20:04 -0700560bool SoundDoseManager::isComputeCsdForcedOnAllDevices() const {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200561 const std::lock_guard _l(mLock);
Vlad Popa91930462022-12-20 22:42:48 +0100562 return mComputeCsdOnAllDevices;
563}
564
Vlad Popa95ee3ca2023-03-20 19:29:38 +0000565bool SoundDoseManager::isSoundDoseHalSupported() const {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200566 {
567 const std::lock_guard _l(mLock);
568 if (!mEnabledCsd) return false;
Vlad Popa95ee3ca2023-03-20 19:29:38 +0000569 }
570
Vlad Popab1c53782023-08-21 19:52:14 -0700571 return useHalSoundDose();
Vlad Popa95ee3ca2023-03-20 19:29:38 +0000572}
573
Vlad Popab1c53782023-08-21 19:52:14 -0700574bool SoundDoseManager::useHalSoundDose() const {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200575 const std::lock_guard _l(mLock);
Vlad Popab1c53782023-08-21 19:52:14 -0700576 return mHalSoundDose.size() > 0;
Vlad Popa3d6d39d2022-12-21 18:59:16 +0100577}
578
Vlad Popae3fd1c22022-11-07 21:03:18 +0100579void SoundDoseManager::resetSoundDose() {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200580 const std::lock_guard lock(mLock);
Vlad Popae3fd1c22022-11-07 21:03:18 +0100581 mSoundDose = nullptr;
582}
583
584void SoundDoseManager::resetCsd(float currentCsd,
585 const std::vector<media::SoundDoseRecord>& records) {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200586 const std::lock_guard lock(mLock);
Vlad Popae3fd1c22022-11-07 21:03:18 +0100587 std::vector<audio_utils::CsdRecord> resetRecords;
Vlad Popaf2cf6742023-06-10 00:24:35 +0200588 resetRecords.reserve(records.size());
Vlad Popae3fd1c22022-11-07 21:03:18 +0100589 for (const auto& record : records) {
590 resetRecords.emplace_back(record.timestamp, record.duration, record.value,
591 record.averageMel);
592 }
593
594 mMelAggregator->reset(currentCsd, resetRecords);
595}
596
Vlad Popa4defd0b2022-11-06 14:22:31 +0100597void SoundDoseManager::onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
598 audio_port_handle_t deviceId) const {
Vlad Popaf09e93f2022-10-31 16:27:12 +0100599 ALOGV("%s", __func__);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200600
Vlad Popa2a06fca2023-02-06 16:45:45 +0100601
Vlad Popa4defd0b2022-11-06 14:22:31 +0100602 sp<media::ISoundDoseCallback> soundDoseCallback;
603 std::vector<audio_utils::CsdRecord> records;
604 float currentCsd;
605 {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200606 const std::lock_guard _l(mLock);
Vlad Popa617bbf02023-04-24 19:10:36 +0200607 if (!mEnabledCsd) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100608 return;
609 }
610
Vlad Popa2900c0a2022-10-24 13:38:00 +0200611
Vlad Popaf2cf6742023-06-10 00:24:35 +0200612 const int64_t timestampSec = getMonotonicSecond();
Vlad Popa4defd0b2022-11-06 14:22:31 +0100613
614 // only for internal callbacks
615 records = mMelAggregator->aggregateAndAddNewMelRecord(audio_utils::MelRecord(
616 deviceId, std::vector<float>(mels.begin() + offset, mels.begin() + offset + length),
617 timestampSec - length));
618
619 currentCsd = mMelAggregator->getCsd();
620 }
621
622 soundDoseCallback = getSoundDoseCallback();
623
624 if (records.size() > 0 && soundDoseCallback != nullptr) {
625 std::vector<media::SoundDoseRecord> newRecordsToReport;
Vlad Popaf2cf6742023-06-10 00:24:35 +0200626 newRecordsToReport.resize(records.size());
Vlad Popa4defd0b2022-11-06 14:22:31 +0100627 for (const auto& record : records) {
628 newRecordsToReport.emplace_back(csdRecordToSoundDoseRecord(record));
629 }
630
631 soundDoseCallback->onNewCsdValue(currentCsd, newRecordsToReport);
632 }
Vlad Popa2900c0a2022-10-24 13:38:00 +0200633}
634
Vlad Popa4defd0b2022-11-06 14:22:31 +0100635sp<media::ISoundDoseCallback> SoundDoseManager::getSoundDoseCallback() const {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200636 const std::lock_guard _l(mLock);
Vlad Popae3fd1c22022-11-07 21:03:18 +0100637 if (mSoundDose == nullptr) {
638 return nullptr;
639 }
640
641 return mSoundDose->mSoundDoseCallback;
Vlad Popa4defd0b2022-11-06 14:22:31 +0100642}
643
644void SoundDoseManager::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const {
645 ALOGV("%s: Momentary exposure for device %d triggered: %f MEL", __func__, deviceId, currentMel);
Vlad Popa63f047e2022-11-05 14:09:19 +0100646
Vlad Popa2a06fca2023-02-06 16:45:45 +0100647 {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200648 const std::lock_guard _l(mLock);
Vlad Popa617bbf02023-04-24 19:10:36 +0200649 if (!mEnabledCsd) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100650 return;
651 }
652 }
653
Vlad Popae3fd1c22022-11-07 21:03:18 +0100654 auto soundDoseCallback = getSoundDoseCallback();
Vlad Popa63f047e2022-11-05 14:09:19 +0100655 if (soundDoseCallback != nullptr) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100656 soundDoseCallback->onMomentaryExposure(currentMel, deviceId);
Vlad Popa63f047e2022-11-05 14:09:19 +0100657 }
658}
659
Vlad Popae3fd1c22022-11-07 21:03:18 +0100660sp<media::ISoundDose> SoundDoseManager::getSoundDoseInterface(
661 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popa63f047e2022-11-05 14:09:19 +0100662 ALOGV("%s: Register ISoundDoseCallback", __func__);
663
Vlad Popaf2cf6742023-06-10 00:24:35 +0200664 const std::lock_guard _l(mLock);
Vlad Popae3fd1c22022-11-07 21:03:18 +0100665 if (mSoundDose == nullptr) {
666 mSoundDose = sp<SoundDose>::make(this, callback);
667 }
668 return mSoundDose;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100669}
670
Vlad Popa4defd0b2022-11-06 14:22:31 +0100671std::string SoundDoseManager::dump() const {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200672 std::string output;
Vlad Popa2a06fca2023-02-06 16:45:45 +0100673 {
Vlad Popaf2cf6742023-06-10 00:24:35 +0200674 const std::lock_guard _l(mLock);
Vlad Popa617bbf02023-04-24 19:10:36 +0200675 if (!mEnabledCsd) {
Vlad Popa2a06fca2023-02-06 16:45:45 +0100676 base::StringAppendF(&output, "CSD is disabled");
677 return output;
678 }
679 }
680
Vlad Popaf09e93f2022-10-31 16:27:12 +0100681 mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200682 base::StringAppendF(&output,
683 "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
Vlad Popa4defd0b2022-11-06 14:22:31 +0100684 csdRecord.value, csdRecord.averageMel, csdRecord.timestamp,
Vlad Popa2900c0a2022-10-24 13:38:00 +0200685 csdRecord.timestamp + csdRecord.duration);
686 base::StringAppendF(&output, "\n");
687 });
688
689 base::StringAppendF(&output, "\nCached Mel Records:\n");
Vlad Popaf09e93f2022-10-31 16:27:12 +0100690 mMelAggregator->foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200691 base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
692 base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
693
694 for (const auto& mel : melRecord.mels) {
695 base::StringAppendF(&output, "%.2f ", mel);
696 }
697 base::StringAppendF(&output, "\n");
698 });
699
700 return output;
701}
702
703size_t SoundDoseManager::getCachedMelRecordsSize() const {
Vlad Popaf09e93f2022-10-31 16:27:12 +0100704 return mMelAggregator->getCachedMelRecordsSize();
Vlad Popa2900c0a2022-10-24 13:38:00 +0200705}
706
Vlad Popa4defd0b2022-11-06 14:22:31 +0100707media::SoundDoseRecord SoundDoseManager::csdRecordToSoundDoseRecord(
708 const audio_utils::CsdRecord& legacy) {
709 media::SoundDoseRecord soundDoseRecord{};
710 soundDoseRecord.timestamp = legacy.timestamp;
711 soundDoseRecord.duration = legacy.duration;
712 soundDoseRecord.value = legacy.value;
713 soundDoseRecord.averageMel = legacy.averageMel;
714 return soundDoseRecord;
715}
716
Vlad Popa2900c0a2022-10-24 13:38:00 +0200717} // namespace android