blob: 474d0cec674a688746841d62c6848aa9a0b98902 [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
23#include <android-base/stringprintf.h>
Vlad Popa2900c0a2022-10-24 13:38:00 +020024#include <time.h>
Vlad Popa4defd0b2022-11-06 14:22:31 +010025#include <utils/Log.h>
26#include <cinttypes>
27#include "android/media/SoundDoseRecord.h"
Vlad Popa2900c0a2022-10-24 13:38:00 +020028
29namespace android {
30
31namespace {
32
33int64_t getMonotonicSecond() {
34 struct timespec now_ts;
35 if (clock_gettime(CLOCK_MONOTONIC, &now_ts) != 0) {
36 ALOGE("%s: cannot get timestamp", __func__);
37 return -1;
38 }
39 return now_ts.tv_sec;
40}
41
42} // namespace
43
Vlad Popaf09e93f2022-10-31 16:27:12 +010044sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
Vlad Popa4defd0b2022-11-06 14:22:31 +010045 audio_port_handle_t deviceId, audio_io_handle_t streamHandle, uint32_t sampleRate,
46 size_t channelCount, audio_format_t format) {
Vlad Popa2900c0a2022-10-24 13:38:00 +020047 std::lock_guard _l(mLock);
48
Vlad Popaf09e93f2022-10-31 16:27:12 +010049 auto streamProcessor = mActiveProcessors.find(streamHandle);
50 sp<audio_utils::MelProcessor> processor;
Vlad Popa4defd0b2022-11-06 14:22:31 +010051 if (streamProcessor != mActiveProcessors.end() &&
52 (processor = streamProcessor->second.promote())) {
Vlad Popa2900c0a2022-10-24 13:38:00 +020053 ALOGV("%s: found callback for stream %d", __func__, streamHandle);
Vlad Popaf09e93f2022-10-31 16:27:12 +010054 processor->setDeviceId(deviceId);
55 return processor;
Vlad Popa2900c0a2022-10-24 13:38:00 +020056 } else {
57 ALOGV("%s: creating new callback for device %d", __func__, streamHandle);
Vlad Popa4defd0b2022-11-06 14:22:31 +010058 sp<audio_utils::MelProcessor> melProcessor = sp<audio_utils::MelProcessor>::make(
59 sampleRate, channelCount, format, *this, deviceId, mRs2Value);
Vlad Popaf09e93f2022-10-31 16:27:12 +010060 mActiveProcessors[streamHandle] = melProcessor;
61 return melProcessor;
Vlad Popa2900c0a2022-10-24 13:38:00 +020062 }
63}
64
Vlad Popa4defd0b2022-11-06 14:22:31 +010065void SoundDoseManager::setOutputRs2(float rs2Value) {
Vlad Popa2900c0a2022-10-24 13:38:00 +020066 ALOGV("%s", __func__);
Vlad Popaf09e93f2022-10-31 16:27:12 +010067 std::lock_guard _l(mLock);
68
69 for (auto& streamProcessor : mActiveProcessors) {
70 sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
71 if (processor != nullptr) {
72 status_t result = processor->setOutputRs2(rs2Value);
73 if (result != NO_ERROR) {
Vlad Popa4defd0b2022-11-06 14:22:31 +010074 ALOGW("%s: could not set RS2 value %f for stream %d", __func__, rs2Value,
Vlad Popaf09e93f2022-10-31 16:27:12 +010075 streamProcessor.first);
76 }
77 }
78 }
79}
80
Vlad Popa4defd0b2022-11-06 14:22:31 +010081void SoundDoseManager::removeStreamProcessor(audio_io_handle_t streamHandle) {
Vlad Popaf09e93f2022-10-31 16:27:12 +010082 std::lock_guard _l(mLock);
83 auto callbackToRemove = mActiveProcessors.find(streamHandle);
Vlad Popa4defd0b2022-11-06 14:22:31 +010084 if (callbackToRemove != mActiveProcessors.end()) {
Vlad Popaf09e93f2022-10-31 16:27:12 +010085 mActiveProcessors.erase(callbackToRemove);
86 }
87}
88
Vlad Popa4defd0b2022-11-06 14:22:31 +010089void SoundDoseManager::onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
90 audio_port_handle_t deviceId) const {
Vlad Popaf09e93f2022-10-31 16:27:12 +010091 ALOGV("%s", __func__);
Vlad Popa2900c0a2022-10-24 13:38:00 +020092
Vlad Popa4defd0b2022-11-06 14:22:31 +010093 sp<media::ISoundDoseCallback> soundDoseCallback;
94 std::vector<audio_utils::CsdRecord> records;
95 float currentCsd;
96 {
97 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +020098
Vlad Popa4defd0b2022-11-06 14:22:31 +010099 int64_t timestampSec = getMonotonicSecond();
100
101 // only for internal callbacks
102 records = mMelAggregator->aggregateAndAddNewMelRecord(audio_utils::MelRecord(
103 deviceId, std::vector<float>(mels.begin() + offset, mels.begin() + offset + length),
104 timestampSec - length));
105
106 currentCsd = mMelAggregator->getCsd();
107 }
108
109 soundDoseCallback = getSoundDoseCallback();
110
111 if (records.size() > 0 && soundDoseCallback != nullptr) {
112 std::vector<media::SoundDoseRecord> newRecordsToReport;
113 for (const auto& record : records) {
114 newRecordsToReport.emplace_back(csdRecordToSoundDoseRecord(record));
115 }
116
117 soundDoseCallback->onNewCsdValue(currentCsd, newRecordsToReport);
118 }
Vlad Popa2900c0a2022-10-24 13:38:00 +0200119}
120
Vlad Popa4defd0b2022-11-06 14:22:31 +0100121sp<media::ISoundDoseCallback> SoundDoseManager::getSoundDoseCallback() const {
122 std::lock_guard _l(mLock);
123 return mSoundDoseCallback;
124}
125
126void SoundDoseManager::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const {
127 ALOGV("%s: Momentary exposure for device %d triggered: %f MEL", __func__, deviceId, currentMel);
Vlad Popa63f047e2022-11-05 14:09:19 +0100128
129 sp<media::ISoundDoseCallback> soundDoseCallback;
130 {
131 std::lock_guard _l(mLock);
132 soundDoseCallback = mSoundDoseCallback;
133 }
134
135 if (soundDoseCallback != nullptr) {
136 mSoundDoseCallback->onMomentaryExposure(currentMel, deviceId);
137 }
138}
139
140void SoundDoseManager::registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) {
141 ALOGV("%s: Register ISoundDoseCallback", __func__);
142
143 std::lock_guard _l(mLock);
144 mSoundDoseCallback = callback;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100145}
146
Vlad Popa4defd0b2022-11-06 14:22:31 +0100147std::string SoundDoseManager::dump() const {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200148 std::string output;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100149 mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200150 base::StringAppendF(&output,
151 "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
Vlad Popa4defd0b2022-11-06 14:22:31 +0100152 csdRecord.value, csdRecord.averageMel, csdRecord.timestamp,
Vlad Popa2900c0a2022-10-24 13:38:00 +0200153 csdRecord.timestamp + csdRecord.duration);
154 base::StringAppendF(&output, "\n");
155 });
156
157 base::StringAppendF(&output, "\nCached Mel Records:\n");
Vlad Popaf09e93f2022-10-31 16:27:12 +0100158 mMelAggregator->foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200159 base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
160 base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
161
162 for (const auto& mel : melRecord.mels) {
163 base::StringAppendF(&output, "%.2f ", mel);
164 }
165 base::StringAppendF(&output, "\n");
166 });
167
168 return output;
169}
170
171size_t SoundDoseManager::getCachedMelRecordsSize() const {
Vlad Popaf09e93f2022-10-31 16:27:12 +0100172 return mMelAggregator->getCachedMelRecordsSize();
Vlad Popa2900c0a2022-10-24 13:38:00 +0200173}
174
Vlad Popa4defd0b2022-11-06 14:22:31 +0100175media::SoundDoseRecord SoundDoseManager::csdRecordToSoundDoseRecord(
176 const audio_utils::CsdRecord& legacy) {
177 media::SoundDoseRecord soundDoseRecord{};
178 soundDoseRecord.timestamp = legacy.timestamp;
179 soundDoseRecord.duration = legacy.duration;
180 soundDoseRecord.value = legacy.value;
181 soundDoseRecord.averageMel = legacy.averageMel;
182 return soundDoseRecord;
183}
184
Vlad Popa2900c0a2022-10-24 13:38:00 +0200185} // namespace android