blob: 0a69c529af425e2d95b9ea3272175d4237ecc909 [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);
126}
127
Vlad Popa2900c0a2022-10-24 13:38:00 +0200128std::string SoundDoseManager::dump() const
129{
130 std::string output;
Vlad Popaf09e93f2022-10-31 16:27:12 +0100131 mMelAggregator->foreachCsd([&output](audio_utils::CsdRecord csdRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200132 base::StringAppendF(&output,
133 "CSD %f with average MEL %f in interval [%" PRId64 ", %" PRId64 "]",
134 csdRecord.value,
135 csdRecord.averageMel,
136 csdRecord.timestamp,
137 csdRecord.timestamp + csdRecord.duration);
138 base::StringAppendF(&output, "\n");
139 });
140
141 base::StringAppendF(&output, "\nCached Mel Records:\n");
Vlad Popaf09e93f2022-10-31 16:27:12 +0100142 mMelAggregator->foreachCachedMel([&output](const audio_utils::MelRecord& melRecord) {
Vlad Popa2900c0a2022-10-24 13:38:00 +0200143 base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
144 base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
145
146 for (const auto& mel : melRecord.mels) {
147 base::StringAppendF(&output, "%.2f ", mel);
148 }
149 base::StringAppendF(&output, "\n");
150 });
151
152 return output;
153}
154
155size_t SoundDoseManager::getCachedMelRecordsSize() const {
Vlad Popaf09e93f2022-10-31 16:27:12 +0100156 return mMelAggregator->getCachedMelRecordsSize();
Vlad Popa2900c0a2022-10-24 13:38:00 +0200157}
158
159} // namespace android