blob: 86fb3a46eea58f10c3bafca980d91ff8be8a8bc8 [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>
24#include <cinttypes>
25#include <utils/Log.h>
26#include <time.h>
27
28namespace android {
29
30namespace {
31
32int64_t getMonotonicSecond() {
33 struct timespec now_ts;
34 if (clock_gettime(CLOCK_MONOTONIC, &now_ts) != 0) {
35 ALOGE("%s: cannot get timestamp", __func__);
36 return -1;
37 }
38 return now_ts.tv_sec;
39}
40
41} // namespace
42
Vlad Popaf09e93f2022-10-31 16:27:12 +010043sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
Vlad Popa2900c0a2022-10-24 13:38:00 +020044 audio_port_handle_t deviceId,
Vlad Popaf09e93f2022-10-31 16:27:12 +010045 audio_io_handle_t streamHandle,
46 uint32_t sampleRate,
47 size_t channelCount,
48 audio_format_t format)
Vlad Popa2900c0a2022-10-24 13:38:00 +020049{
50 std::lock_guard _l(mLock);
51
Vlad Popaf09e93f2022-10-31 16:27:12 +010052 auto streamProcessor = mActiveProcessors.find(streamHandle);
53 sp<audio_utils::MelProcessor> processor;
54 if (streamProcessor != mActiveProcessors.end()
55 && (processor = streamProcessor->second.promote())) {
Vlad Popa2900c0a2022-10-24 13:38:00 +020056 ALOGV("%s: found callback for stream %d", __func__, streamHandle);
Vlad Popaf09e93f2022-10-31 16:27:12 +010057 processor->setDeviceId(deviceId);
58 return processor;
Vlad Popa2900c0a2022-10-24 13:38:00 +020059 } else {
60 ALOGV("%s: creating new callback for device %d", __func__, streamHandle);
Vlad Popaf09e93f2022-10-31 16:27:12 +010061 sp<audio_utils::MelProcessor> melProcessor =
62 sp<audio_utils::MelProcessor>::make(sampleRate,
63 channelCount,
64 format,
65 *this,
66 deviceId,
67 mRs2Value);
68 mActiveProcessors[streamHandle] = melProcessor;
69 return melProcessor;
Vlad Popa2900c0a2022-10-24 13:38:00 +020070 }
71}
72
Vlad Popa2900c0a2022-10-24 13:38:00 +020073
Vlad Popaf09e93f2022-10-31 16:27:12 +010074void SoundDoseManager::setOutputRs2(float rs2Value)
Vlad Popa2900c0a2022-10-24 13:38:00 +020075{
76 ALOGV("%s", __func__);
Vlad Popaf09e93f2022-10-31 16:27:12 +010077 std::lock_guard _l(mLock);
78
79 for (auto& streamProcessor : mActiveProcessors) {
80 sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
81 if (processor != nullptr) {
82 status_t result = processor->setOutputRs2(rs2Value);
83 if (result != NO_ERROR) {
84 ALOGW("%s: could not set RS2 value %f for stream %d",
85 __func__,
86 rs2Value,
87 streamProcessor.first);
88 }
89 }
90 }
91}
92
93void SoundDoseManager::removeStreamProcessor(audio_io_handle_t streamHandle)
94{
95 std::lock_guard _l(mLock);
96 auto callbackToRemove = mActiveProcessors.find(streamHandle);
97 if(callbackToRemove != mActiveProcessors.end()) {
98 mActiveProcessors.erase(callbackToRemove);
99 }
100}
101
102void SoundDoseManager::onNewMelValues(const std::vector<float>& mels,
103 size_t offset,
104 size_t length,
105 audio_port_handle_t deviceId) const
106{
107 ALOGV("%s", __func__);
108 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200109
110 int64_t timestampSec = getMonotonicSecond();
111
112 // only for internal callbacks
Vlad Popaf09e93f2022-10-31 16:27:12 +0100113 mMelAggregator->aggregateAndAddNewMelRecord(
114 audio_utils::MelRecord(deviceId, std::vector<float>(
Vlad Popa2900c0a2022-10-24 13:38:00 +0200115 mels.begin() + offset,
116 mels.begin() + offset + length),
117 timestampSec - length));
118}
119
Vlad Popaf09e93f2022-10-31 16:27:12 +0100120void SoundDoseManager::onMomentaryExposure(float currentMel,
121 audio_port_handle_t deviceId) const {
122 ALOGV("%s: Momentary exposure for device %d triggered: %f MEL",
123 __func__,
124 deviceId,
125 currentMel);
Vlad Popa63f047e2022-11-05 14:09:19 +0100126
127 sp<media::ISoundDoseCallback> soundDoseCallback;
128 {
129 std::lock_guard _l(mLock);
130 soundDoseCallback = mSoundDoseCallback;
131 }
132
133 if (soundDoseCallback != nullptr) {
134 mSoundDoseCallback->onMomentaryExposure(currentMel, deviceId);
135 }
136}
137
138void SoundDoseManager::registerSoundDoseCallback(const sp<media::ISoundDoseCallback>& callback) {
139 ALOGV("%s: Register ISoundDoseCallback", __func__);
140
141 std::lock_guard _l(mLock);
142 mSoundDoseCallback = callback;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100143}
144
Vlad Popa2900c0a2022-10-24 13:38:00 +0200145std::string SoundDoseManager::dump() const
146{
147 std::string output;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100148 mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200149 base::StringAppendF(&output,
150 "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
151 csdRecord.value,
152 csdRecord.averageMel,
153 csdRecord.timestamp,
154 csdRecord.timestamp + csdRecord.duration);
155 base::StringAppendF(&output, "\n");
156 });
157
158 base::StringAppendF(&output, "\nCached Mel Records:\n");
Vlad Popaf09e93f2022-10-31 16:27:12 +0100159 mMelAggregator->foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200160 base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
161 base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
162
163 for (const auto& mel : melRecord.mels) {
164 base::StringAppendF(&output, "%.2f ", mel);
165 }
166 base::StringAppendF(&output, "\n");
167 });
168
169 return output;
170}
171
172size_t SoundDoseManager::getCachedMelRecordsSize() const {
Vlad Popaf09e93f2022-10-31 16:27:12 +0100173 return mMelAggregator->getCachedMelRecordsSize();
Vlad Popa2900c0a2022-10-24 13:38:00 +0200174}
175
176} // namespace android