1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2022, The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker
18*ec779b8eSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "SoundDoseManager"
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include "SoundDoseManager.h"
22*ec779b8eSAndroid Build Coastguard Worker
23*ec779b8eSAndroid Build Coastguard Worker #include "android/media/SoundDoseRecord.h"
24*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
25*ec779b8eSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <cinttypes>
27*ec779b8eSAndroid Build Coastguard Worker #include <ctime>
28*ec779b8eSAndroid Build Coastguard Worker #include <functional>
29*ec779b8eSAndroid Build Coastguard Worker #include <media/AidlConversionCppNdk.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker namespace android {
33*ec779b8eSAndroid Build Coastguard Worker
34*ec779b8eSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioDevice;
35*ec779b8eSAndroid Build Coastguard Worker
36*ec779b8eSAndroid Build Coastguard Worker namespace {
37*ec779b8eSAndroid Build Coastguard Worker
38*ec779b8eSAndroid Build Coastguard Worker // Port handle used when CSD is computed on all devices. Should be a different value than
39*ec779b8eSAndroid Build Coastguard Worker // AUDIO_PORT_HANDLE_NONE which is associated with a sound dose callback failure
40*ec779b8eSAndroid Build Coastguard Worker constexpr audio_port_handle_t CSD_ON_ALL_DEVICES_PORT_HANDLE = -1;
41*ec779b8eSAndroid Build Coastguard Worker
getMonotonicSecond()42*ec779b8eSAndroid Build Coastguard Worker int64_t getMonotonicSecond() {
43*ec779b8eSAndroid Build Coastguard Worker struct timespec now_ts;
44*ec779b8eSAndroid Build Coastguard Worker if (clock_gettime(CLOCK_MONOTONIC, &now_ts) != 0) {
45*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: cannot get timestamp", __func__);
46*ec779b8eSAndroid Build Coastguard Worker return -1;
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker return now_ts.tv_sec;
49*ec779b8eSAndroid Build Coastguard Worker }
50*ec779b8eSAndroid Build Coastguard Worker
51*ec779b8eSAndroid Build Coastguard Worker constexpr float kDefaultRs2LowerBound = 80.f; // dBA
52*ec779b8eSAndroid Build Coastguard Worker
53*ec779b8eSAndroid Build Coastguard Worker } // namespace
54*ec779b8eSAndroid Build Coastguard Worker
getOrCreateProcessorForDevice(audio_port_handle_t deviceId,audio_io_handle_t streamHandle,uint32_t sampleRate,size_t channelCount,audio_format_t format)55*ec779b8eSAndroid Build Coastguard Worker sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
56*ec779b8eSAndroid Build Coastguard Worker audio_port_handle_t deviceId, audio_io_handle_t streamHandle, uint32_t sampleRate,
57*ec779b8eSAndroid Build Coastguard Worker size_t channelCount, audio_format_t format) {
58*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
59*ec779b8eSAndroid Build Coastguard Worker
60*ec779b8eSAndroid Build Coastguard Worker if (!mUseFrameworkMel && mHalSoundDose.size() > 0 && mEnabledCsd) {
61*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
62*ec779b8eSAndroid Build Coastguard Worker return nullptr;
63*ec779b8eSAndroid Build Coastguard Worker }
64*ec779b8eSAndroid Build Coastguard Worker
65*ec779b8eSAndroid Build Coastguard Worker auto streamProcessor = mActiveProcessors.find(streamHandle);
66*ec779b8eSAndroid Build Coastguard Worker if (streamProcessor != mActiveProcessors.end()) {
67*ec779b8eSAndroid Build Coastguard Worker auto processor = streamProcessor->second.promote();
68*ec779b8eSAndroid Build Coastguard Worker // if processor is nullptr it means it was removed by the playback
69*ec779b8eSAndroid Build Coastguard Worker // thread and can be replaced in the mActiveProcessors map
70*ec779b8eSAndroid Build Coastguard Worker if (processor != nullptr) {
71*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: found callback for stream id %d", __func__, streamHandle);
72*ec779b8eSAndroid Build Coastguard Worker const auto activeTypeIt = mActiveDeviceTypes.find(deviceId);
73*ec779b8eSAndroid Build Coastguard Worker if (activeTypeIt != mActiveDeviceTypes.end()) {
74*ec779b8eSAndroid Build Coastguard Worker processor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]);
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker processor->setDeviceId(deviceId);
77*ec779b8eSAndroid Build Coastguard Worker processor->setOutputRs2UpperBound(mRs2UpperBound);
78*ec779b8eSAndroid Build Coastguard Worker return processor;
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker }
81*ec779b8eSAndroid Build Coastguard Worker
82*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: creating new callback for stream id %d", __func__, streamHandle);
83*ec779b8eSAndroid Build Coastguard Worker sp<audio_utils::MelProcessor> melProcessor = sp<audio_utils::MelProcessor>::make(
84*ec779b8eSAndroid Build Coastguard Worker sampleRate, channelCount, format, this, deviceId, mRs2UpperBound);
85*ec779b8eSAndroid Build Coastguard Worker const auto activeTypeIt = mActiveDeviceTypes.find(deviceId);
86*ec779b8eSAndroid Build Coastguard Worker if (activeTypeIt != mActiveDeviceTypes.end()) {
87*ec779b8eSAndroid Build Coastguard Worker melProcessor->setAttenuation(mMelAttenuationDB[activeTypeIt->second]);
88*ec779b8eSAndroid Build Coastguard Worker }
89*ec779b8eSAndroid Build Coastguard Worker mActiveProcessors[streamHandle] = melProcessor;
90*ec779b8eSAndroid Build Coastguard Worker return melProcessor;
91*ec779b8eSAndroid Build Coastguard Worker }
92*ec779b8eSAndroid Build Coastguard Worker
setHalSoundDoseInterface(const std::string & module,const std::shared_ptr<ISoundDose> & halSoundDose)93*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::setHalSoundDoseInterface(const std::string &module,
94*ec779b8eSAndroid Build Coastguard Worker const std::shared_ptr<ISoundDose> &halSoundDose) {
95*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
96*ec779b8eSAndroid Build Coastguard Worker
97*ec779b8eSAndroid Build Coastguard Worker if (halSoundDose == nullptr) {
98*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: passed ISoundDose object is null", __func__);
99*ec779b8eSAndroid Build Coastguard Worker return false;
100*ec779b8eSAndroid Build Coastguard Worker }
101*ec779b8eSAndroid Build Coastguard Worker
102*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<HalSoundDoseCallback> halSoundDoseCallback;
103*ec779b8eSAndroid Build Coastguard Worker {
104*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
105*ec779b8eSAndroid Build Coastguard Worker
106*ec779b8eSAndroid Build Coastguard Worker if (mHalSoundDose.find(module) != mHalSoundDose.end()) {
107*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: Module %s already has a sound dose HAL assigned, skipping", __func__,
108*ec779b8eSAndroid Build Coastguard Worker module.c_str());
109*ec779b8eSAndroid Build Coastguard Worker return false;
110*ec779b8eSAndroid Build Coastguard Worker }
111*ec779b8eSAndroid Build Coastguard Worker mHalSoundDose[module] = halSoundDose;
112*ec779b8eSAndroid Build Coastguard Worker
113*ec779b8eSAndroid Build Coastguard Worker if (!halSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
114*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
115*ec779b8eSAndroid Build Coastguard Worker __func__,
116*ec779b8eSAndroid Build Coastguard Worker mRs2UpperBound);
117*ec779b8eSAndroid Build Coastguard Worker }
118*ec779b8eSAndroid Build Coastguard Worker
119*ec779b8eSAndroid Build Coastguard Worker // initialize the HAL sound dose callback lazily
120*ec779b8eSAndroid Build Coastguard Worker if (mHalSoundDoseCallback == nullptr) {
121*ec779b8eSAndroid Build Coastguard Worker mHalSoundDoseCallback =
122*ec779b8eSAndroid Build Coastguard Worker ndk::SharedRefBase::make<HalSoundDoseCallback>(this);
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker halSoundDoseCallback = mHalSoundDoseCallback;
125*ec779b8eSAndroid Build Coastguard Worker }
126*ec779b8eSAndroid Build Coastguard Worker
127*ec779b8eSAndroid Build Coastguard Worker auto status = halSoundDose->registerSoundDoseCallback(halSoundDoseCallback);
128*ec779b8eSAndroid Build Coastguard Worker
129*ec779b8eSAndroid Build Coastguard Worker if (!status.isOk()) {
130*ec779b8eSAndroid Build Coastguard Worker // Not a warning since this can happen if the callback was registered before
131*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: Cannot register HAL sound dose callback with status message: %s",
132*ec779b8eSAndroid Build Coastguard Worker __func__,
133*ec779b8eSAndroid Build Coastguard Worker status.getMessage());
134*ec779b8eSAndroid Build Coastguard Worker }
135*ec779b8eSAndroid Build Coastguard Worker
136*ec779b8eSAndroid Build Coastguard Worker return true;
137*ec779b8eSAndroid Build Coastguard Worker }
138*ec779b8eSAndroid Build Coastguard Worker
resetHalSoundDoseInterfaces()139*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::resetHalSoundDoseInterfaces() {
140*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
141*ec779b8eSAndroid Build Coastguard Worker
142*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
143*ec779b8eSAndroid Build Coastguard Worker mHalSoundDose.clear();
144*ec779b8eSAndroid Build Coastguard Worker }
145*ec779b8eSAndroid Build Coastguard Worker
setOutputRs2UpperBound(float rs2Value)146*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::setOutputRs2UpperBound(float rs2Value) {
147*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
148*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
149*ec779b8eSAndroid Build Coastguard Worker
150*ec779b8eSAndroid Build Coastguard Worker if (!mUseFrameworkMel && mHalSoundDose.size() > 0) {
151*ec779b8eSAndroid Build Coastguard Worker bool success = true;
152*ec779b8eSAndroid Build Coastguard Worker for (auto& halSoundDose : mHalSoundDose) {
153*ec779b8eSAndroid Build Coastguard Worker // using the HAL sound dose interface
154*ec779b8eSAndroid Build Coastguard Worker if (!halSoundDose.second->setOutputRs2UpperBound(rs2Value).isOk()) {
155*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
156*ec779b8eSAndroid Build Coastguard Worker success = false;
157*ec779b8eSAndroid Build Coastguard Worker break;
158*ec779b8eSAndroid Build Coastguard Worker }
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker
161*ec779b8eSAndroid Build Coastguard Worker if (success) {
162*ec779b8eSAndroid Build Coastguard Worker mRs2UpperBound = rs2Value;
163*ec779b8eSAndroid Build Coastguard Worker } else {
164*ec779b8eSAndroid Build Coastguard Worker // restore all RS2 upper bounds to the previous value
165*ec779b8eSAndroid Build Coastguard Worker for (auto& halSoundDose : mHalSoundDose) {
166*ec779b8eSAndroid Build Coastguard Worker halSoundDose.second->setOutputRs2UpperBound(mRs2UpperBound);
167*ec779b8eSAndroid Build Coastguard Worker }
168*ec779b8eSAndroid Build Coastguard Worker }
169*ec779b8eSAndroid Build Coastguard Worker return;
170*ec779b8eSAndroid Build Coastguard Worker }
171*ec779b8eSAndroid Build Coastguard Worker
172*ec779b8eSAndroid Build Coastguard Worker for (auto& streamProcessor : mActiveProcessors) {
173*ec779b8eSAndroid Build Coastguard Worker const sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
174*ec779b8eSAndroid Build Coastguard Worker if (processor != nullptr) {
175*ec779b8eSAndroid Build Coastguard Worker const status_t result = processor->setOutputRs2UpperBound(rs2Value);
176*ec779b8eSAndroid Build Coastguard Worker if (result != NO_ERROR) {
177*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: could not set RS2 upper bound %f for stream %d", __func__, rs2Value,
178*ec779b8eSAndroid Build Coastguard Worker streamProcessor.first);
179*ec779b8eSAndroid Build Coastguard Worker return;
180*ec779b8eSAndroid Build Coastguard Worker }
181*ec779b8eSAndroid Build Coastguard Worker mRs2UpperBound = rs2Value;
182*ec779b8eSAndroid Build Coastguard Worker }
183*ec779b8eSAndroid Build Coastguard Worker }
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker
removeStreamProcessor(audio_io_handle_t streamHandle)186*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::removeStreamProcessor(audio_io_handle_t streamHandle) {
187*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
188*ec779b8eSAndroid Build Coastguard Worker auto callbackToRemove = mActiveProcessors.find(streamHandle);
189*ec779b8eSAndroid Build Coastguard Worker if (callbackToRemove != mActiveProcessors.end()) {
190*ec779b8eSAndroid Build Coastguard Worker mActiveProcessors.erase(callbackToRemove);
191*ec779b8eSAndroid Build Coastguard Worker }
192*ec779b8eSAndroid Build Coastguard Worker }
193*ec779b8eSAndroid Build Coastguard Worker
getAttenuationForDeviceId(audio_port_handle_t id) const194*ec779b8eSAndroid Build Coastguard Worker float SoundDoseManager::getAttenuationForDeviceId(audio_port_handle_t id) const {
195*ec779b8eSAndroid Build Coastguard Worker float attenuation = 0.f;
196*ec779b8eSAndroid Build Coastguard Worker
197*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
198*ec779b8eSAndroid Build Coastguard Worker const auto deviceTypeIt = mActiveDeviceTypes.find(id);
199*ec779b8eSAndroid Build Coastguard Worker if (deviceTypeIt != mActiveDeviceTypes.end()) {
200*ec779b8eSAndroid Build Coastguard Worker auto attenuationIt = mMelAttenuationDB.find(deviceTypeIt->second);
201*ec779b8eSAndroid Build Coastguard Worker if (attenuationIt != mMelAttenuationDB.end()) {
202*ec779b8eSAndroid Build Coastguard Worker attenuation = attenuationIt->second;
203*ec779b8eSAndroid Build Coastguard Worker }
204*ec779b8eSAndroid Build Coastguard Worker }
205*ec779b8eSAndroid Build Coastguard Worker
206*ec779b8eSAndroid Build Coastguard Worker return attenuation;
207*ec779b8eSAndroid Build Coastguard Worker }
208*ec779b8eSAndroid Build Coastguard Worker
getIdForAudioDevice(const AudioDevice & audioDevice) const209*ec779b8eSAndroid Build Coastguard Worker audio_port_handle_t SoundDoseManager::getIdForAudioDevice(const AudioDevice& audioDevice) const {
210*ec779b8eSAndroid Build Coastguard Worker if (isComputeCsdForcedOnAllDevices()) {
211*ec779b8eSAndroid Build Coastguard Worker // If CSD is forced on all devices return random port id. Used only in testing.
212*ec779b8eSAndroid Build Coastguard Worker // This is necessary since the patches that are registered before
213*ec779b8eSAndroid Build Coastguard Worker // setComputeCsdOnAllDevices will not be contributing to mActiveDevices
214*ec779b8eSAndroid Build Coastguard Worker return CSD_ON_ALL_DEVICES_PORT_HANDLE;
215*ec779b8eSAndroid Build Coastguard Worker }
216*ec779b8eSAndroid Build Coastguard Worker
217*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
218*ec779b8eSAndroid Build Coastguard Worker
219*ec779b8eSAndroid Build Coastguard Worker audio_devices_t type;
220*ec779b8eSAndroid Build Coastguard Worker std::string address;
221*ec779b8eSAndroid Build Coastguard Worker auto result = aidl::android::aidl2legacy_AudioDevice_audio_device(
222*ec779b8eSAndroid Build Coastguard Worker audioDevice, &type, &address);
223*ec779b8eSAndroid Build Coastguard Worker if (result != NO_ERROR) {
224*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: could not convert from AudioDevice to AudioDeviceTypeAddr", __func__);
225*ec779b8eSAndroid Build Coastguard Worker return AUDIO_PORT_HANDLE_NONE;
226*ec779b8eSAndroid Build Coastguard Worker }
227*ec779b8eSAndroid Build Coastguard Worker
228*ec779b8eSAndroid Build Coastguard Worker auto adt = AudioDeviceTypeAddr(type, address);
229*ec779b8eSAndroid Build Coastguard Worker auto deviceIt = mActiveDevices.find(adt);
230*ec779b8eSAndroid Build Coastguard Worker if (deviceIt == mActiveDevices.end()) {
231*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: could not find port id for device %s", __func__, adt.toString().c_str());
232*ec779b8eSAndroid Build Coastguard Worker return AUDIO_PORT_HANDLE_NONE;
233*ec779b8eSAndroid Build Coastguard Worker }
234*ec779b8eSAndroid Build Coastguard Worker
235*ec779b8eSAndroid Build Coastguard Worker if (audio_is_ble_out_device(type) || audio_is_a2dp_device(type)) {
236*ec779b8eSAndroid Build Coastguard Worker const auto btDeviceIt = mBluetoothDevicesWithCsd.find(std::make_pair(address, type));
237*ec779b8eSAndroid Build Coastguard Worker if (btDeviceIt == mBluetoothDevicesWithCsd.end() || !btDeviceIt->second) {
238*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: bt device %s does not support sound dose", __func__,
239*ec779b8eSAndroid Build Coastguard Worker adt.toString().c_str());
240*ec779b8eSAndroid Build Coastguard Worker return AUDIO_PORT_HANDLE_NONE;
241*ec779b8eSAndroid Build Coastguard Worker }
242*ec779b8eSAndroid Build Coastguard Worker }
243*ec779b8eSAndroid Build Coastguard Worker return deviceIt->second;
244*ec779b8eSAndroid Build Coastguard Worker }
245*ec779b8eSAndroid Build Coastguard Worker
mapAddressToDeviceId(const AudioDeviceTypeAddr & adt,const audio_port_handle_t deviceId)246*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
247*ec779b8eSAndroid Build Coastguard Worker const audio_port_handle_t deviceId) {
248*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
249*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: map address: %d to device id: %d", __func__, adt.mType, deviceId);
250*ec779b8eSAndroid Build Coastguard Worker mActiveDevices[adt] = deviceId;
251*ec779b8eSAndroid Build Coastguard Worker mActiveDeviceTypes[deviceId] = adt.mType;
252*ec779b8eSAndroid Build Coastguard Worker }
253*ec779b8eSAndroid Build Coastguard Worker
clearMapDeviceIdEntries(audio_port_handle_t deviceId)254*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) {
255*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
256*ec779b8eSAndroid Build Coastguard Worker for (auto activeDevice = mActiveDevices.begin(); activeDevice != mActiveDevices.end();) {
257*ec779b8eSAndroid Build Coastguard Worker if (activeDevice->second == deviceId) {
258*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: clear mapping type: %d to deviceId: %d",
259*ec779b8eSAndroid Build Coastguard Worker __func__, activeDevice->first.mType, deviceId);
260*ec779b8eSAndroid Build Coastguard Worker activeDevice = mActiveDevices.erase(activeDevice);
261*ec779b8eSAndroid Build Coastguard Worker continue;
262*ec779b8eSAndroid Build Coastguard Worker }
263*ec779b8eSAndroid Build Coastguard Worker ++activeDevice;
264*ec779b8eSAndroid Build Coastguard Worker }
265*ec779b8eSAndroid Build Coastguard Worker mActiveDeviceTypes.erase(deviceId);
266*ec779b8eSAndroid Build Coastguard Worker }
267*ec779b8eSAndroid Build Coastguard Worker
onMomentaryExposureWarning(float in_currentDbA,const AudioDevice & in_audioDevice)268*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
269*ec779b8eSAndroid Build Coastguard Worker float in_currentDbA, const AudioDevice& in_audioDevice) {
270*ec779b8eSAndroid Build Coastguard Worker sp<SoundDoseManager> soundDoseManager;
271*ec779b8eSAndroid Build Coastguard Worker {
272*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mCbLock);
273*ec779b8eSAndroid Build Coastguard Worker soundDoseManager = mSoundDoseManager.promote();
274*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager == nullptr) {
275*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
276*ec779b8eSAndroid Build Coastguard Worker }
277*ec779b8eSAndroid Build Coastguard Worker }
278*ec779b8eSAndroid Build Coastguard Worker
279*ec779b8eSAndroid Build Coastguard Worker if (!soundDoseManager->useHalSoundDose()) {
280*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
281*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
282*ec779b8eSAndroid Build Coastguard Worker }
283*ec779b8eSAndroid Build Coastguard Worker
284*ec779b8eSAndroid Build Coastguard Worker auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
285*ec779b8eSAndroid Build Coastguard Worker if (id == AUDIO_PORT_HANDLE_NONE) {
286*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: no mapped id for audio device with type %d and address %s",
287*ec779b8eSAndroid Build Coastguard Worker __func__, static_cast<int>(in_audioDevice.type.type),
288*ec779b8eSAndroid Build Coastguard Worker in_audioDevice.address.toString().c_str());
289*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
290*ec779b8eSAndroid Build Coastguard Worker }
291*ec779b8eSAndroid Build Coastguard Worker
292*ec779b8eSAndroid Build Coastguard Worker float attenuation = soundDoseManager->getAttenuationForDeviceId(id);
293*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: attenuating received momentary exposure with %f dB", __func__, attenuation);
294*ec779b8eSAndroid Build Coastguard Worker // TODO: remove attenuation when enforcing HAL MELs to always be attenuated
295*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->onMomentaryExposure(in_currentDbA - attenuation, id);
296*ec779b8eSAndroid Build Coastguard Worker
297*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
298*ec779b8eSAndroid Build Coastguard Worker }
299*ec779b8eSAndroid Build Coastguard Worker
onNewMelValues(const ISoundDose::IHalSoundDoseCallback::MelRecord & in_melRecord,const AudioDevice & in_audioDevice)300*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
301*ec779b8eSAndroid Build Coastguard Worker const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
302*ec779b8eSAndroid Build Coastguard Worker const AudioDevice& in_audioDevice) {
303*ec779b8eSAndroid Build Coastguard Worker sp<SoundDoseManager> soundDoseManager;
304*ec779b8eSAndroid Build Coastguard Worker {
305*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mCbLock);
306*ec779b8eSAndroid Build Coastguard Worker soundDoseManager = mSoundDoseManager.promote();
307*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager == nullptr) {
308*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
309*ec779b8eSAndroid Build Coastguard Worker }
310*ec779b8eSAndroid Build Coastguard Worker }
311*ec779b8eSAndroid Build Coastguard Worker
312*ec779b8eSAndroid Build Coastguard Worker if (!soundDoseManager->useHalSoundDose()) {
313*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
314*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
315*ec779b8eSAndroid Build Coastguard Worker }
316*ec779b8eSAndroid Build Coastguard Worker
317*ec779b8eSAndroid Build Coastguard Worker auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
318*ec779b8eSAndroid Build Coastguard Worker if (id == AUDIO_PORT_HANDLE_NONE) {
319*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: no mapped id for audio device with type %d and address %s",
320*ec779b8eSAndroid Build Coastguard Worker __func__, static_cast<int>(in_audioDevice.type.type),
321*ec779b8eSAndroid Build Coastguard Worker in_audioDevice.address.toString().c_str());
322*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
323*ec779b8eSAndroid Build Coastguard Worker }
324*ec779b8eSAndroid Build Coastguard Worker
325*ec779b8eSAndroid Build Coastguard Worker // TODO: introduce timestamp in onNewMelValues callback
326*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->onNewMelValues(in_melRecord.melValues, 0, in_melRecord.melValues.size(),
327*ec779b8eSAndroid Build Coastguard Worker id, /*attenuated=*/false);
328*ec779b8eSAndroid Build Coastguard Worker
329*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
330*ec779b8eSAndroid Build Coastguard Worker }
331*ec779b8eSAndroid Build Coastguard Worker
binderDied(__unused const wp<IBinder> & who)332*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::SoundDose::binderDied(__unused const wp<IBinder>& who) {
333*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
334*ec779b8eSAndroid Build Coastguard Worker
335*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
336*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
337*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->resetSoundDose();
338*ec779b8eSAndroid Build Coastguard Worker }
339*ec779b8eSAndroid Build Coastguard Worker }
340*ec779b8eSAndroid Build Coastguard Worker
setOutputRs2UpperBound(float value)341*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::setOutputRs2UpperBound(float value) {
342*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
343*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
344*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
345*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->setOutputRs2UpperBound(value);
346*ec779b8eSAndroid Build Coastguard Worker }
347*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
348*ec779b8eSAndroid Build Coastguard Worker }
349*ec779b8eSAndroid Build Coastguard Worker
resetCsd(float currentCsd,const std::vector<media::SoundDoseRecord> & records)350*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::resetCsd(
351*ec779b8eSAndroid Build Coastguard Worker float currentCsd, const std::vector<media::SoundDoseRecord>& records) {
352*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
353*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
354*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
355*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->resetCsd(currentCsd, records);
356*ec779b8eSAndroid Build Coastguard Worker }
357*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
358*ec779b8eSAndroid Build Coastguard Worker }
359*ec779b8eSAndroid Build Coastguard Worker
updateAttenuation(float attenuationDB,int device)360*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::updateAttenuation(float attenuationDB, int device) {
361*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
362*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
363*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
364*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->updateAttenuation(attenuationDB, static_cast<audio_devices_t>(device));
365*ec779b8eSAndroid Build Coastguard Worker }
366*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
367*ec779b8eSAndroid Build Coastguard Worker }
368*ec779b8eSAndroid Build Coastguard Worker
setCsdEnabled(bool enabled)369*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::setCsdEnabled(bool enabled) {
370*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
371*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
372*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
373*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->setCsdEnabled(enabled);
374*ec779b8eSAndroid Build Coastguard Worker }
375*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
376*ec779b8eSAndroid Build Coastguard Worker }
377*ec779b8eSAndroid Build Coastguard Worker
initCachedAudioDeviceCategories(const std::vector<media::ISoundDose::AudioDeviceCategory> & btDeviceCategories)378*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::initCachedAudioDeviceCategories(
379*ec779b8eSAndroid Build Coastguard Worker const std::vector<media::ISoundDose::AudioDeviceCategory>& btDeviceCategories) {
380*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
381*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
382*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
383*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->initCachedAudioDeviceCategories(btDeviceCategories);
384*ec779b8eSAndroid Build Coastguard Worker }
385*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
386*ec779b8eSAndroid Build Coastguard Worker }
setAudioDeviceCategory(const media::ISoundDose::AudioDeviceCategory & btAudioDevice)387*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::setAudioDeviceCategory(
388*ec779b8eSAndroid Build Coastguard Worker const media::ISoundDose::AudioDeviceCategory& btAudioDevice) {
389*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
390*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
391*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
392*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->setAudioDeviceCategory(btAudioDevice);
393*ec779b8eSAndroid Build Coastguard Worker }
394*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
395*ec779b8eSAndroid Build Coastguard Worker }
396*ec779b8eSAndroid Build Coastguard Worker
getOutputRs2UpperBound(float * value)397*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::getOutputRs2UpperBound(float* value) {
398*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
399*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
400*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
401*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(soundDoseManager->mLock);
402*ec779b8eSAndroid Build Coastguard Worker *value = soundDoseManager->mRs2UpperBound;
403*ec779b8eSAndroid Build Coastguard Worker }
404*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
405*ec779b8eSAndroid Build Coastguard Worker }
406*ec779b8eSAndroid Build Coastguard Worker
getCsd(float * value)407*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::getCsd(float* value) {
408*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
409*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
410*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
411*ec779b8eSAndroid Build Coastguard Worker *value = soundDoseManager->mMelAggregator->getCsd();
412*ec779b8eSAndroid Build Coastguard Worker }
413*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
414*ec779b8eSAndroid Build Coastguard Worker }
415*ec779b8eSAndroid Build Coastguard Worker
forceUseFrameworkMel(bool useFrameworkMel)416*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::forceUseFrameworkMel(bool useFrameworkMel) {
417*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
418*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
419*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
420*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->setUseFrameworkMel(useFrameworkMel);
421*ec779b8eSAndroid Build Coastguard Worker }
422*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
423*ec779b8eSAndroid Build Coastguard Worker }
424*ec779b8eSAndroid Build Coastguard Worker
forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices)425*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::forceComputeCsdOnAllDevices(
426*ec779b8eSAndroid Build Coastguard Worker bool computeCsdOnAllDevices) {
427*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
428*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
429*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
430*ec779b8eSAndroid Build Coastguard Worker soundDoseManager->setComputeCsdOnAllDevices(computeCsdOnAllDevices);
431*ec779b8eSAndroid Build Coastguard Worker }
432*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
433*ec779b8eSAndroid Build Coastguard Worker }
434*ec779b8eSAndroid Build Coastguard Worker
isSoundDoseHalSupported(bool * value)435*ec779b8eSAndroid Build Coastguard Worker binder::Status SoundDoseManager::SoundDose::isSoundDoseHalSupported(bool* value) {
436*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
437*ec779b8eSAndroid Build Coastguard Worker *value = false;
438*ec779b8eSAndroid Build Coastguard Worker auto soundDoseManager = mSoundDoseManager.promote();
439*ec779b8eSAndroid Build Coastguard Worker if (soundDoseManager != nullptr) {
440*ec779b8eSAndroid Build Coastguard Worker *value = soundDoseManager->isSoundDoseHalSupported();
441*ec779b8eSAndroid Build Coastguard Worker }
442*ec779b8eSAndroid Build Coastguard Worker return binder::Status::ok();
443*ec779b8eSAndroid Build Coastguard Worker }
444*ec779b8eSAndroid Build Coastguard Worker
updateAttenuation(float attenuationDB,audio_devices_t deviceType)445*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::updateAttenuation(float attenuationDB, audio_devices_t deviceType) {
446*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
447*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: updating MEL processor attenuation for device type %d to %f",
448*ec779b8eSAndroid Build Coastguard Worker __func__, deviceType, attenuationDB);
449*ec779b8eSAndroid Build Coastguard Worker mMelAttenuationDB[deviceType] = attenuationDB;
450*ec779b8eSAndroid Build Coastguard Worker for (const auto& mp : mActiveProcessors) {
451*ec779b8eSAndroid Build Coastguard Worker auto melProcessor = mp.second.promote();
452*ec779b8eSAndroid Build Coastguard Worker if (melProcessor != nullptr) {
453*ec779b8eSAndroid Build Coastguard Worker auto deviceId = melProcessor->getDeviceId();
454*ec779b8eSAndroid Build Coastguard Worker const auto deviceTypeIt = mActiveDeviceTypes.find(deviceId);
455*ec779b8eSAndroid Build Coastguard Worker if (deviceTypeIt != mActiveDeviceTypes.end() &&
456*ec779b8eSAndroid Build Coastguard Worker deviceTypeIt->second == deviceType) {
457*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: set attenuation for deviceId %d to %f",
458*ec779b8eSAndroid Build Coastguard Worker __func__, deviceId, attenuationDB);
459*ec779b8eSAndroid Build Coastguard Worker melProcessor->setAttenuation(attenuationDB);
460*ec779b8eSAndroid Build Coastguard Worker }
461*ec779b8eSAndroid Build Coastguard Worker }
462*ec779b8eSAndroid Build Coastguard Worker }
463*ec779b8eSAndroid Build Coastguard Worker }
464*ec779b8eSAndroid Build Coastguard Worker
setCsdEnabled(bool enabled)465*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::setCsdEnabled(bool enabled) {
466*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
467*ec779b8eSAndroid Build Coastguard Worker
468*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
469*ec779b8eSAndroid Build Coastguard Worker mEnabledCsd = enabled;
470*ec779b8eSAndroid Build Coastguard Worker
471*ec779b8eSAndroid Build Coastguard Worker for (auto& activeEntry : mActiveProcessors) {
472*ec779b8eSAndroid Build Coastguard Worker auto melProcessor = activeEntry.second.promote();
473*ec779b8eSAndroid Build Coastguard Worker if (melProcessor != nullptr) {
474*ec779b8eSAndroid Build Coastguard Worker if (enabled) {
475*ec779b8eSAndroid Build Coastguard Worker melProcessor->resume();
476*ec779b8eSAndroid Build Coastguard Worker } else {
477*ec779b8eSAndroid Build Coastguard Worker melProcessor->pause();
478*ec779b8eSAndroid Build Coastguard Worker }
479*ec779b8eSAndroid Build Coastguard Worker }
480*ec779b8eSAndroid Build Coastguard Worker }
481*ec779b8eSAndroid Build Coastguard Worker }
482*ec779b8eSAndroid Build Coastguard Worker
isCsdEnabled()483*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::isCsdEnabled() {
484*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
485*ec779b8eSAndroid Build Coastguard Worker return mEnabledCsd;
486*ec779b8eSAndroid Build Coastguard Worker }
487*ec779b8eSAndroid Build Coastguard Worker
initCachedAudioDeviceCategories(const std::vector<media::ISoundDose::AudioDeviceCategory> & deviceCategories)488*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::initCachedAudioDeviceCategories(
489*ec779b8eSAndroid Build Coastguard Worker const std::vector<media::ISoundDose::AudioDeviceCategory>& deviceCategories) {
490*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
491*ec779b8eSAndroid Build Coastguard Worker {
492*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
493*ec779b8eSAndroid Build Coastguard Worker mBluetoothDevicesWithCsd.clear();
494*ec779b8eSAndroid Build Coastguard Worker }
495*ec779b8eSAndroid Build Coastguard Worker for (const auto& btDeviceCategory : deviceCategories) {
496*ec779b8eSAndroid Build Coastguard Worker setAudioDeviceCategory(btDeviceCategory);
497*ec779b8eSAndroid Build Coastguard Worker }
498*ec779b8eSAndroid Build Coastguard Worker }
499*ec779b8eSAndroid Build Coastguard Worker
setAudioDeviceCategory(const media::ISoundDose::AudioDeviceCategory & audioDevice)500*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::setAudioDeviceCategory(
501*ec779b8eSAndroid Build Coastguard Worker const media::ISoundDose::AudioDeviceCategory& audioDevice) {
502*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: set BT audio device type with address %s to headphone %d", __func__,
503*ec779b8eSAndroid Build Coastguard Worker audioDevice.address.c_str(), audioDevice.csdCompatible);
504*ec779b8eSAndroid Build Coastguard Worker
505*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_port_handle_t> devicesToStart;
506*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_port_handle_t> devicesToStop;
507*ec779b8eSAndroid Build Coastguard Worker {
508*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
509*ec779b8eSAndroid Build Coastguard Worker const auto deviceIt = mBluetoothDevicesWithCsd.find(
510*ec779b8eSAndroid Build Coastguard Worker std::make_pair(audioDevice.address,
511*ec779b8eSAndroid Build Coastguard Worker static_cast<audio_devices_t>(audioDevice.internalAudioType)));
512*ec779b8eSAndroid Build Coastguard Worker if (deviceIt != mBluetoothDevicesWithCsd.end()) {
513*ec779b8eSAndroid Build Coastguard Worker deviceIt->second = audioDevice.csdCompatible;
514*ec779b8eSAndroid Build Coastguard Worker } else {
515*ec779b8eSAndroid Build Coastguard Worker mBluetoothDevicesWithCsd.emplace(
516*ec779b8eSAndroid Build Coastguard Worker std::make_pair(audioDevice.address,
517*ec779b8eSAndroid Build Coastguard Worker static_cast<audio_devices_t>(audioDevice.internalAudioType)),
518*ec779b8eSAndroid Build Coastguard Worker audioDevice.csdCompatible);
519*ec779b8eSAndroid Build Coastguard Worker }
520*ec779b8eSAndroid Build Coastguard Worker
521*ec779b8eSAndroid Build Coastguard Worker for (const auto &activeDevice: mActiveDevices) {
522*ec779b8eSAndroid Build Coastguard Worker if (activeDevice.first.address() == audioDevice.address &&
523*ec779b8eSAndroid Build Coastguard Worker activeDevice.first.mType ==
524*ec779b8eSAndroid Build Coastguard Worker static_cast<audio_devices_t>(audioDevice.internalAudioType)) {
525*ec779b8eSAndroid Build Coastguard Worker if (audioDevice.csdCompatible) {
526*ec779b8eSAndroid Build Coastguard Worker devicesToStart.push_back(activeDevice.second);
527*ec779b8eSAndroid Build Coastguard Worker } else {
528*ec779b8eSAndroid Build Coastguard Worker devicesToStop.push_back(activeDevice.second);
529*ec779b8eSAndroid Build Coastguard Worker }
530*ec779b8eSAndroid Build Coastguard Worker }
531*ec779b8eSAndroid Build Coastguard Worker }
532*ec779b8eSAndroid Build Coastguard Worker }
533*ec779b8eSAndroid Build Coastguard Worker
534*ec779b8eSAndroid Build Coastguard Worker for (const auto& deviceToStart : devicesToStart) {
535*ec779b8eSAndroid Build Coastguard Worker mMelReporterCallback->startMelComputationForDeviceId(deviceToStart);
536*ec779b8eSAndroid Build Coastguard Worker }
537*ec779b8eSAndroid Build Coastguard Worker for (const auto& deviceToStop : devicesToStop) {
538*ec779b8eSAndroid Build Coastguard Worker mMelReporterCallback->stopMelComputationForDeviceId(deviceToStop);
539*ec779b8eSAndroid Build Coastguard Worker }
540*ec779b8eSAndroid Build Coastguard Worker }
541*ec779b8eSAndroid Build Coastguard Worker
shouldComputeCsdForDeviceType(audio_devices_t device)542*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::shouldComputeCsdForDeviceType(audio_devices_t device) {
543*ec779b8eSAndroid Build Coastguard Worker if (!isCsdEnabled()) {
544*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s csd is disabled", __func__);
545*ec779b8eSAndroid Build Coastguard Worker return false;
546*ec779b8eSAndroid Build Coastguard Worker }
547*ec779b8eSAndroid Build Coastguard Worker if (isComputeCsdForcedOnAllDevices()) {
548*ec779b8eSAndroid Build Coastguard Worker return true;
549*ec779b8eSAndroid Build Coastguard Worker }
550*ec779b8eSAndroid Build Coastguard Worker
551*ec779b8eSAndroid Build Coastguard Worker switch (device) {
552*ec779b8eSAndroid Build Coastguard Worker case AUDIO_DEVICE_OUT_WIRED_HEADSET:
553*ec779b8eSAndroid Build Coastguard Worker case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
554*ec779b8eSAndroid Build Coastguard Worker case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
555*ec779b8eSAndroid Build Coastguard Worker case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
556*ec779b8eSAndroid Build Coastguard Worker case AUDIO_DEVICE_OUT_USB_HEADSET:
557*ec779b8eSAndroid Build Coastguard Worker case AUDIO_DEVICE_OUT_BLE_HEADSET:
558*ec779b8eSAndroid Build Coastguard Worker case AUDIO_DEVICE_OUT_BLE_BROADCAST:
559*ec779b8eSAndroid Build Coastguard Worker return true;
560*ec779b8eSAndroid Build Coastguard Worker default:
561*ec779b8eSAndroid Build Coastguard Worker return false;
562*ec779b8eSAndroid Build Coastguard Worker }
563*ec779b8eSAndroid Build Coastguard Worker }
564*ec779b8eSAndroid Build Coastguard Worker
shouldComputeCsdForDeviceWithAddress(const audio_devices_t type,const std::string & deviceAddress)565*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::shouldComputeCsdForDeviceWithAddress(const audio_devices_t type,
566*ec779b8eSAndroid Build Coastguard Worker const std::string& deviceAddress) {
567*ec779b8eSAndroid Build Coastguard Worker if (!isCsdEnabled()) {
568*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s csd is disabled", __func__);
569*ec779b8eSAndroid Build Coastguard Worker return false;
570*ec779b8eSAndroid Build Coastguard Worker }
571*ec779b8eSAndroid Build Coastguard Worker if (isComputeCsdForcedOnAllDevices()) {
572*ec779b8eSAndroid Build Coastguard Worker return true;
573*ec779b8eSAndroid Build Coastguard Worker }
574*ec779b8eSAndroid Build Coastguard Worker
575*ec779b8eSAndroid Build Coastguard Worker if (!audio_is_ble_out_device(type) && !audio_is_a2dp_device(type)) {
576*ec779b8eSAndroid Build Coastguard Worker return shouldComputeCsdForDeviceType(type);
577*ec779b8eSAndroid Build Coastguard Worker }
578*ec779b8eSAndroid Build Coastguard Worker
579*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
580*ec779b8eSAndroid Build Coastguard Worker const auto deviceIt = mBluetoothDevicesWithCsd.find(std::make_pair(deviceAddress, type));
581*ec779b8eSAndroid Build Coastguard Worker return deviceIt != mBluetoothDevicesWithCsd.end() && deviceIt->second;
582*ec779b8eSAndroid Build Coastguard Worker }
583*ec779b8eSAndroid Build Coastguard Worker
setUseFrameworkMel(bool useFrameworkMel)584*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
585*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
586*ec779b8eSAndroid Build Coastguard Worker mUseFrameworkMel = useFrameworkMel;
587*ec779b8eSAndroid Build Coastguard Worker }
588*ec779b8eSAndroid Build Coastguard Worker
isFrameworkMelForced() const589*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::isFrameworkMelForced() const {
590*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
591*ec779b8eSAndroid Build Coastguard Worker return mUseFrameworkMel;
592*ec779b8eSAndroid Build Coastguard Worker }
593*ec779b8eSAndroid Build Coastguard Worker
setComputeCsdOnAllDevices(bool computeCsdOnAllDevices)594*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::setComputeCsdOnAllDevices(bool computeCsdOnAllDevices) {
595*ec779b8eSAndroid Build Coastguard Worker bool changed = false;
596*ec779b8eSAndroid Build Coastguard Worker {
597*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
598*ec779b8eSAndroid Build Coastguard Worker if (mHalSoundDose.size() != 0) {
599*ec779b8eSAndroid Build Coastguard Worker // when using the HAL path we cannot enforce to deliver values for all devices
600*ec779b8eSAndroid Build Coastguard Worker changed = mUseFrameworkMel != computeCsdOnAllDevices;
601*ec779b8eSAndroid Build Coastguard Worker mUseFrameworkMel = computeCsdOnAllDevices;
602*ec779b8eSAndroid Build Coastguard Worker }
603*ec779b8eSAndroid Build Coastguard Worker mComputeCsdOnAllDevices = computeCsdOnAllDevices;
604*ec779b8eSAndroid Build Coastguard Worker }
605*ec779b8eSAndroid Build Coastguard Worker if (changed && computeCsdOnAllDevices) {
606*ec779b8eSAndroid Build Coastguard Worker mMelReporterCallback->applyAllAudioPatches();
607*ec779b8eSAndroid Build Coastguard Worker }
608*ec779b8eSAndroid Build Coastguard Worker }
609*ec779b8eSAndroid Build Coastguard Worker
isComputeCsdForcedOnAllDevices() const610*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::isComputeCsdForcedOnAllDevices() const {
611*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
612*ec779b8eSAndroid Build Coastguard Worker return mComputeCsdOnAllDevices;
613*ec779b8eSAndroid Build Coastguard Worker }
614*ec779b8eSAndroid Build Coastguard Worker
isSoundDoseHalSupported() const615*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::isSoundDoseHalSupported() const {
616*ec779b8eSAndroid Build Coastguard Worker {
617*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
618*ec779b8eSAndroid Build Coastguard Worker if (!mEnabledCsd) return false;
619*ec779b8eSAndroid Build Coastguard Worker }
620*ec779b8eSAndroid Build Coastguard Worker
621*ec779b8eSAndroid Build Coastguard Worker return useHalSoundDose();
622*ec779b8eSAndroid Build Coastguard Worker }
623*ec779b8eSAndroid Build Coastguard Worker
useHalSoundDose() const624*ec779b8eSAndroid Build Coastguard Worker bool SoundDoseManager::useHalSoundDose() const {
625*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
626*ec779b8eSAndroid Build Coastguard Worker return !mUseFrameworkMel && mHalSoundDose.size() > 0;
627*ec779b8eSAndroid Build Coastguard Worker }
628*ec779b8eSAndroid Build Coastguard Worker
resetSoundDose()629*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::resetSoundDose() {
630*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard lock(mLock);
631*ec779b8eSAndroid Build Coastguard Worker mSoundDose = nullptr;
632*ec779b8eSAndroid Build Coastguard Worker }
633*ec779b8eSAndroid Build Coastguard Worker
resetCsd(float currentCsd,const std::vector<media::SoundDoseRecord> & records)634*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::resetCsd(float currentCsd,
635*ec779b8eSAndroid Build Coastguard Worker const std::vector<media::SoundDoseRecord>& records) {
636*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard lock(mLock);
637*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_utils::CsdRecord> resetRecords;
638*ec779b8eSAndroid Build Coastguard Worker resetRecords.reserve(records.size());
639*ec779b8eSAndroid Build Coastguard Worker for (const auto& record : records) {
640*ec779b8eSAndroid Build Coastguard Worker resetRecords.emplace_back(record.timestamp, record.duration, record.value,
641*ec779b8eSAndroid Build Coastguard Worker record.averageMel);
642*ec779b8eSAndroid Build Coastguard Worker }
643*ec779b8eSAndroid Build Coastguard Worker
644*ec779b8eSAndroid Build Coastguard Worker mMelAggregator->reset(currentCsd, resetRecords);
645*ec779b8eSAndroid Build Coastguard Worker }
646*ec779b8eSAndroid Build Coastguard Worker
onNewMelValues(const std::vector<float> & mels,size_t offset,size_t length,audio_port_handle_t deviceId,bool attenuated) const647*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
648*ec779b8eSAndroid Build Coastguard Worker audio_port_handle_t deviceId, bool attenuated) const {
649*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s", __func__);
650*ec779b8eSAndroid Build Coastguard Worker
651*ec779b8eSAndroid Build Coastguard Worker sp<media::ISoundDoseCallback> soundDoseCallback;
652*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_utils::CsdRecord> records;
653*ec779b8eSAndroid Build Coastguard Worker float currentCsd;
654*ec779b8eSAndroid Build Coastguard Worker
655*ec779b8eSAndroid Build Coastguard Worker // TODO: delete this case when enforcing HAL MELs to always be attenuated
656*ec779b8eSAndroid Build Coastguard Worker float attenuation = attenuated ? 0.0f : getAttenuationForDeviceId(deviceId);
657*ec779b8eSAndroid Build Coastguard Worker
658*ec779b8eSAndroid Build Coastguard Worker {
659*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
660*ec779b8eSAndroid Build Coastguard Worker if (!mEnabledCsd) {
661*ec779b8eSAndroid Build Coastguard Worker return;
662*ec779b8eSAndroid Build Coastguard Worker }
663*ec779b8eSAndroid Build Coastguard Worker
664*ec779b8eSAndroid Build Coastguard Worker const int64_t timestampSec = getMonotonicSecond();
665*ec779b8eSAndroid Build Coastguard Worker
666*ec779b8eSAndroid Build Coastguard Worker if (attenuated) {
667*ec779b8eSAndroid Build Coastguard Worker records = mMelAggregator->aggregateAndAddNewMelRecord(audio_utils::MelRecord(
668*ec779b8eSAndroid Build Coastguard Worker deviceId,
669*ec779b8eSAndroid Build Coastguard Worker std::vector<float>(mels.begin() + offset, mels.begin() + offset + length),
670*ec779b8eSAndroid Build Coastguard Worker timestampSec - length));
671*ec779b8eSAndroid Build Coastguard Worker } else {
672*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: attenuating received values with %f dB", __func__, attenuation);
673*ec779b8eSAndroid Build Coastguard Worker
674*ec779b8eSAndroid Build Coastguard Worker // Extracting all intervals that contain values >= RS2 low limit (80dBA) after the
675*ec779b8eSAndroid Build Coastguard Worker // attenuation is applied
676*ec779b8eSAndroid Build Coastguard Worker size_t start = offset;
677*ec779b8eSAndroid Build Coastguard Worker size_t stop = offset;
678*ec779b8eSAndroid Build Coastguard Worker for (; stop < mels.size() && stop < offset + length; ++stop) {
679*ec779b8eSAndroid Build Coastguard Worker if (mels[stop] - attenuation < kDefaultRs2LowerBound) {
680*ec779b8eSAndroid Build Coastguard Worker if (start < stop) {
681*ec779b8eSAndroid Build Coastguard Worker std::vector<float> attMel(stop-start, -attenuation);
682*ec779b8eSAndroid Build Coastguard Worker // attMel[i] = mels[i] + attenuation, i in [start, stop)
683*ec779b8eSAndroid Build Coastguard Worker std::transform(mels.begin() + start, mels.begin() + stop, attMel.begin(),
684*ec779b8eSAndroid Build Coastguard Worker attMel.begin(), std::plus<float>());
685*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_utils::CsdRecord> newRec =
686*ec779b8eSAndroid Build Coastguard Worker mMelAggregator->aggregateAndAddNewMelRecord(
687*ec779b8eSAndroid Build Coastguard Worker audio_utils::MelRecord(deviceId,
688*ec779b8eSAndroid Build Coastguard Worker attMel,
689*ec779b8eSAndroid Build Coastguard Worker timestampSec - length + start -
690*ec779b8eSAndroid Build Coastguard Worker offset));
691*ec779b8eSAndroid Build Coastguard Worker std::copy(newRec.begin(), newRec.end(), std::back_inserter(records));
692*ec779b8eSAndroid Build Coastguard Worker }
693*ec779b8eSAndroid Build Coastguard Worker start = stop+1;
694*ec779b8eSAndroid Build Coastguard Worker }
695*ec779b8eSAndroid Build Coastguard Worker }
696*ec779b8eSAndroid Build Coastguard Worker if (start < stop) {
697*ec779b8eSAndroid Build Coastguard Worker std::vector<float> attMel(stop-start, -attenuation);
698*ec779b8eSAndroid Build Coastguard Worker // attMel[i] = mels[i] + attenuation, i in [start, stop)
699*ec779b8eSAndroid Build Coastguard Worker std::transform(mels.begin() + start, mels.begin() + stop, attMel.begin(),
700*ec779b8eSAndroid Build Coastguard Worker attMel.begin(), std::plus<float>());
701*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_utils::CsdRecord> newRec =
702*ec779b8eSAndroid Build Coastguard Worker mMelAggregator->aggregateAndAddNewMelRecord(
703*ec779b8eSAndroid Build Coastguard Worker audio_utils::MelRecord(deviceId,
704*ec779b8eSAndroid Build Coastguard Worker attMel,
705*ec779b8eSAndroid Build Coastguard Worker timestampSec - length + start -
706*ec779b8eSAndroid Build Coastguard Worker offset));
707*ec779b8eSAndroid Build Coastguard Worker std::copy(newRec.begin(), newRec.end(), std::back_inserter(records));
708*ec779b8eSAndroid Build Coastguard Worker }
709*ec779b8eSAndroid Build Coastguard Worker }
710*ec779b8eSAndroid Build Coastguard Worker
711*ec779b8eSAndroid Build Coastguard Worker currentCsd = mMelAggregator->getCsd();
712*ec779b8eSAndroid Build Coastguard Worker }
713*ec779b8eSAndroid Build Coastguard Worker
714*ec779b8eSAndroid Build Coastguard Worker soundDoseCallback = getSoundDoseCallback();
715*ec779b8eSAndroid Build Coastguard Worker
716*ec779b8eSAndroid Build Coastguard Worker if (records.size() > 0 && soundDoseCallback != nullptr) {
717*ec779b8eSAndroid Build Coastguard Worker std::vector<media::SoundDoseRecord> newRecordsToReport;
718*ec779b8eSAndroid Build Coastguard Worker newRecordsToReport.resize(records.size());
719*ec779b8eSAndroid Build Coastguard Worker for (const auto& record : records) {
720*ec779b8eSAndroid Build Coastguard Worker newRecordsToReport.emplace_back(csdRecordToSoundDoseRecord(record));
721*ec779b8eSAndroid Build Coastguard Worker }
722*ec779b8eSAndroid Build Coastguard Worker
723*ec779b8eSAndroid Build Coastguard Worker soundDoseCallback->onNewCsdValue(currentCsd, newRecordsToReport);
724*ec779b8eSAndroid Build Coastguard Worker }
725*ec779b8eSAndroid Build Coastguard Worker }
726*ec779b8eSAndroid Build Coastguard Worker
getSoundDoseCallback() const727*ec779b8eSAndroid Build Coastguard Worker sp<media::ISoundDoseCallback> SoundDoseManager::getSoundDoseCallback() const {
728*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
729*ec779b8eSAndroid Build Coastguard Worker if (mSoundDose == nullptr) {
730*ec779b8eSAndroid Build Coastguard Worker return nullptr;
731*ec779b8eSAndroid Build Coastguard Worker }
732*ec779b8eSAndroid Build Coastguard Worker
733*ec779b8eSAndroid Build Coastguard Worker return mSoundDose->mSoundDoseCallback;
734*ec779b8eSAndroid Build Coastguard Worker }
735*ec779b8eSAndroid Build Coastguard Worker
onMomentaryExposure(float currentMel,audio_port_handle_t deviceId) const736*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const {
737*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: Momentary exposure for device %d triggered: %f MEL", __func__, deviceId, currentMel);
738*ec779b8eSAndroid Build Coastguard Worker
739*ec779b8eSAndroid Build Coastguard Worker {
740*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
741*ec779b8eSAndroid Build Coastguard Worker if (!mEnabledCsd) {
742*ec779b8eSAndroid Build Coastguard Worker return;
743*ec779b8eSAndroid Build Coastguard Worker }
744*ec779b8eSAndroid Build Coastguard Worker
745*ec779b8eSAndroid Build Coastguard Worker if (currentMel < mRs2UpperBound) {
746*ec779b8eSAndroid Build Coastguard Worker return;
747*ec779b8eSAndroid Build Coastguard Worker }
748*ec779b8eSAndroid Build Coastguard Worker }
749*ec779b8eSAndroid Build Coastguard Worker
750*ec779b8eSAndroid Build Coastguard Worker auto soundDoseCallback = getSoundDoseCallback();
751*ec779b8eSAndroid Build Coastguard Worker if (soundDoseCallback != nullptr) {
752*ec779b8eSAndroid Build Coastguard Worker soundDoseCallback->onMomentaryExposure(currentMel, deviceId);
753*ec779b8eSAndroid Build Coastguard Worker }
754*ec779b8eSAndroid Build Coastguard Worker }
755*ec779b8eSAndroid Build Coastguard Worker
resetReferencesForTest()756*ec779b8eSAndroid Build Coastguard Worker void SoundDoseManager::resetReferencesForTest() {
757*ec779b8eSAndroid Build Coastguard Worker mMelReporterCallback.clear();
758*ec779b8eSAndroid Build Coastguard Worker }
759*ec779b8eSAndroid Build Coastguard Worker
getSoundDoseInterface(const sp<media::ISoundDoseCallback> & callback)760*ec779b8eSAndroid Build Coastguard Worker sp<media::ISoundDose> SoundDoseManager::getSoundDoseInterface(
761*ec779b8eSAndroid Build Coastguard Worker const sp<media::ISoundDoseCallback>& callback) {
762*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: Register ISoundDoseCallback", __func__);
763*ec779b8eSAndroid Build Coastguard Worker
764*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
765*ec779b8eSAndroid Build Coastguard Worker if (mSoundDose == nullptr) {
766*ec779b8eSAndroid Build Coastguard Worker mSoundDose = sp<SoundDose>::make(this, callback);
767*ec779b8eSAndroid Build Coastguard Worker }
768*ec779b8eSAndroid Build Coastguard Worker return mSoundDose;
769*ec779b8eSAndroid Build Coastguard Worker }
770*ec779b8eSAndroid Build Coastguard Worker
dump() const771*ec779b8eSAndroid Build Coastguard Worker std::string SoundDoseManager::dump() const {
772*ec779b8eSAndroid Build Coastguard Worker std::string output;
773*ec779b8eSAndroid Build Coastguard Worker {
774*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard _l(mLock);
775*ec779b8eSAndroid Build Coastguard Worker if (!mEnabledCsd) {
776*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output, "CSD is disabled");
777*ec779b8eSAndroid Build Coastguard Worker return output;
778*ec779b8eSAndroid Build Coastguard Worker }
779*ec779b8eSAndroid Build Coastguard Worker }
780*ec779b8eSAndroid Build Coastguard Worker
781*ec779b8eSAndroid Build Coastguard Worker mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
782*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output,
783*ec779b8eSAndroid Build Coastguard Worker "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
784*ec779b8eSAndroid Build Coastguard Worker csdRecord.value, csdRecord.averageMel, csdRecord.timestamp,
785*ec779b8eSAndroid Build Coastguard Worker csdRecord.timestamp + csdRecord.duration);
786*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output, "\n");
787*ec779b8eSAndroid Build Coastguard Worker });
788*ec779b8eSAndroid Build Coastguard Worker
789*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output, "\nCached Mel Records:\n");
790*ec779b8eSAndroid Build Coastguard Worker mMelAggregator->foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
791*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
792*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
793*ec779b8eSAndroid Build Coastguard Worker
794*ec779b8eSAndroid Build Coastguard Worker for (const auto& mel : melRecord.mels) {
795*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output, "%.2f ", mel);
796*ec779b8eSAndroid Build Coastguard Worker }
797*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&output, "\n");
798*ec779b8eSAndroid Build Coastguard Worker });
799*ec779b8eSAndroid Build Coastguard Worker
800*ec779b8eSAndroid Build Coastguard Worker return output;
801*ec779b8eSAndroid Build Coastguard Worker }
802*ec779b8eSAndroid Build Coastguard Worker
getCachedMelRecordsSize() const803*ec779b8eSAndroid Build Coastguard Worker size_t SoundDoseManager::getCachedMelRecordsSize() const {
804*ec779b8eSAndroid Build Coastguard Worker return mMelAggregator->getCachedMelRecordsSize();
805*ec779b8eSAndroid Build Coastguard Worker }
806*ec779b8eSAndroid Build Coastguard Worker
csdRecordToSoundDoseRecord(const audio_utils::CsdRecord & legacy)807*ec779b8eSAndroid Build Coastguard Worker media::SoundDoseRecord SoundDoseManager::csdRecordToSoundDoseRecord(
808*ec779b8eSAndroid Build Coastguard Worker const audio_utils::CsdRecord& legacy) {
809*ec779b8eSAndroid Build Coastguard Worker media::SoundDoseRecord soundDoseRecord{};
810*ec779b8eSAndroid Build Coastguard Worker soundDoseRecord.timestamp = legacy.timestamp;
811*ec779b8eSAndroid Build Coastguard Worker soundDoseRecord.duration = legacy.duration;
812*ec779b8eSAndroid Build Coastguard Worker soundDoseRecord.value = legacy.value;
813*ec779b8eSAndroid Build Coastguard Worker soundDoseRecord.averageMel = legacy.averageMel;
814*ec779b8eSAndroid Build Coastguard Worker return soundDoseRecord;
815*ec779b8eSAndroid Build Coastguard Worker }
816*ec779b8eSAndroid Build Coastguard Worker
817*ec779b8eSAndroid Build Coastguard Worker } // namespace android
818