1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "AHAL_SoundDose"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include "core-impl/SoundDose.h"
20*4d7e907cSAndroid Build Coastguard Worker
21*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/audio/core/sounddose/ISoundDose.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <media/AidlConversionCppNdk.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <utils/Timers.h>
25*4d7e907cSAndroid Build Coastguard Worker
26*4d7e907cSAndroid Build Coastguard Worker using aidl::android::hardware::audio::core::sounddose::ISoundDose;
27*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioDevice;
28*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioDeviceDescription;
29*4d7e907cSAndroid Build Coastguard Worker using aidl::android::media::audio::common::AudioFormatDescription;
30*4d7e907cSAndroid Build Coastguard Worker
31*4d7e907cSAndroid Build Coastguard Worker namespace aidl::android::hardware::audio::core::sounddose {
32*4d7e907cSAndroid Build Coastguard Worker
setOutputRs2UpperBound(float in_rs2ValueDbA)33*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus SoundDose::setOutputRs2UpperBound(float in_rs2ValueDbA) {
34*4d7e907cSAndroid Build Coastguard Worker if (in_rs2ValueDbA < MIN_RS2 || in_rs2ValueDbA > DEFAULT_MAX_RS2) {
35*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": RS2 value is invalid: " << in_rs2ValueDbA;
36*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
37*4d7e907cSAndroid Build Coastguard Worker }
38*4d7e907cSAndroid Build Coastguard Worker
39*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mMutex);
40*4d7e907cSAndroid Build Coastguard Worker mRs2Value = in_rs2ValueDbA;
41*4d7e907cSAndroid Build Coastguard Worker if (mMelProcessor != nullptr) {
42*4d7e907cSAndroid Build Coastguard Worker mMelProcessor->setOutputRs2UpperBound(in_rs2ValueDbA);
43*4d7e907cSAndroid Build Coastguard Worker }
44*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
45*4d7e907cSAndroid Build Coastguard Worker }
46*4d7e907cSAndroid Build Coastguard Worker
getOutputRs2UpperBound(float * _aidl_return)47*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus SoundDose::getOutputRs2UpperBound(float* _aidl_return) {
48*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mMutex);
49*4d7e907cSAndroid Build Coastguard Worker *_aidl_return = mRs2Value;
50*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
51*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
52*4d7e907cSAndroid Build Coastguard Worker }
53*4d7e907cSAndroid Build Coastguard Worker
registerSoundDoseCallback(const std::shared_ptr<ISoundDose::IHalSoundDoseCallback> & in_callback)54*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus SoundDose::registerSoundDoseCallback(
55*4d7e907cSAndroid Build Coastguard Worker const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& in_callback) {
56*4d7e907cSAndroid Build Coastguard Worker if (in_callback.get() == nullptr) {
57*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": Callback is nullptr";
58*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
59*4d7e907cSAndroid Build Coastguard Worker }
60*4d7e907cSAndroid Build Coastguard Worker
61*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mCbMutex);
62*4d7e907cSAndroid Build Coastguard Worker if (mCallback != nullptr) {
63*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": Sound dose callback was already registered";
64*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
65*4d7e907cSAndroid Build Coastguard Worker }
66*4d7e907cSAndroid Build Coastguard Worker
67*4d7e907cSAndroid Build Coastguard Worker mCallback = in_callback;
68*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << __func__ << ": Registered sound dose callback ";
69*4d7e907cSAndroid Build Coastguard Worker
70*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
71*4d7e907cSAndroid Build Coastguard Worker }
72*4d7e907cSAndroid Build Coastguard Worker
setAudioDevice(const AudioDevice & audioDevice)73*4d7e907cSAndroid Build Coastguard Worker void SoundDose::setAudioDevice(const AudioDevice& audioDevice) {
74*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mCbMutex);
75*4d7e907cSAndroid Build Coastguard Worker mAudioDevice = audioDevice;
76*4d7e907cSAndroid Build Coastguard Worker }
77*4d7e907cSAndroid Build Coastguard Worker
startDataProcessor(uint32_t sampleRate,uint32_t channelCount,const AudioFormatDescription & aidlFormat)78*4d7e907cSAndroid Build Coastguard Worker void SoundDose::startDataProcessor(uint32_t sampleRate, uint32_t channelCount,
79*4d7e907cSAndroid Build Coastguard Worker const AudioFormatDescription& aidlFormat) {
80*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mMutex);
81*4d7e907cSAndroid Build Coastguard Worker const auto result = aidl2legacy_AudioFormatDescription_audio_format_t(aidlFormat);
82*4d7e907cSAndroid Build Coastguard Worker const audio_format_t format = result.value_or(AUDIO_FORMAT_INVALID);
83*4d7e907cSAndroid Build Coastguard Worker
84*4d7e907cSAndroid Build Coastguard Worker if (mMelProcessor == nullptr) {
85*4d7e907cSAndroid Build Coastguard Worker // we don't have the deviceId concept on the vendor side so just pass 0
86*4d7e907cSAndroid Build Coastguard Worker mMelProcessor = ::android::sp<::android::audio_utils::MelProcessor>::make(
87*4d7e907cSAndroid Build Coastguard Worker sampleRate, channelCount, format, mMelCallback, /*deviceId=*/0, mRs2Value);
88*4d7e907cSAndroid Build Coastguard Worker } else {
89*4d7e907cSAndroid Build Coastguard Worker mMelProcessor->updateAudioFormat(sampleRate, channelCount, format);
90*4d7e907cSAndroid Build Coastguard Worker }
91*4d7e907cSAndroid Build Coastguard Worker }
92*4d7e907cSAndroid Build Coastguard Worker
process(const void * buffer,size_t bytes)93*4d7e907cSAndroid Build Coastguard Worker void SoundDose::process(const void* buffer, size_t bytes) {
94*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mMutex);
95*4d7e907cSAndroid Build Coastguard Worker if (mMelProcessor != nullptr) {
96*4d7e907cSAndroid Build Coastguard Worker mMelProcessor->process(buffer, bytes);
97*4d7e907cSAndroid Build Coastguard Worker }
98*4d7e907cSAndroid Build Coastguard Worker }
99*4d7e907cSAndroid Build Coastguard Worker
onNewMelValues(const std::vector<float> & mels,size_t offset,size_t length,audio_port_handle_t deviceId) const100*4d7e907cSAndroid Build Coastguard Worker void SoundDose::onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length,
101*4d7e907cSAndroid Build Coastguard Worker audio_port_handle_t deviceId __attribute__((__unused__))) const {
102*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mCbMutex);
103*4d7e907cSAndroid Build Coastguard Worker if (!mAudioDevice.has_value()) {
104*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << __func__ << ": New mel values without a registered device";
105*4d7e907cSAndroid Build Coastguard Worker return;
106*4d7e907cSAndroid Build Coastguard Worker }
107*4d7e907cSAndroid Build Coastguard Worker if (mCallback == nullptr) {
108*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": New mel values without a registered callback";
109*4d7e907cSAndroid Build Coastguard Worker return;
110*4d7e907cSAndroid Build Coastguard Worker }
111*4d7e907cSAndroid Build Coastguard Worker
112*4d7e907cSAndroid Build Coastguard Worker ISoundDose::IHalSoundDoseCallback::MelRecord melRecord;
113*4d7e907cSAndroid Build Coastguard Worker melRecord.timestamp = nanoseconds_to_seconds(systemTime());
114*4d7e907cSAndroid Build Coastguard Worker melRecord.melValues = std::vector<float>(mels.begin() + offset, mels.begin() + offset + length);
115*4d7e907cSAndroid Build Coastguard Worker
116*4d7e907cSAndroid Build Coastguard Worker mCallback->onNewMelValues(melRecord, mAudioDevice.value());
117*4d7e907cSAndroid Build Coastguard Worker }
118*4d7e907cSAndroid Build Coastguard Worker
onNewMelValues(const std::vector<float> & mels,size_t offset,size_t length,audio_port_handle_t deviceId,bool attenuated) const119*4d7e907cSAndroid Build Coastguard Worker void SoundDose::MelCallback::onNewMelValues(const std::vector<float>& mels, size_t offset,
120*4d7e907cSAndroid Build Coastguard Worker size_t length,
121*4d7e907cSAndroid Build Coastguard Worker audio_port_handle_t deviceId
122*4d7e907cSAndroid Build Coastguard Worker __attribute__((__unused__)),
123*4d7e907cSAndroid Build Coastguard Worker bool attenuated __attribute__((__unused__))) const {
124*4d7e907cSAndroid Build Coastguard Worker mSoundDose.onNewMelValues(mels, offset, length, deviceId);
125*4d7e907cSAndroid Build Coastguard Worker }
126*4d7e907cSAndroid Build Coastguard Worker
onMomentaryExposure(float currentMel,audio_port_handle_t deviceId) const127*4d7e907cSAndroid Build Coastguard Worker void SoundDose::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId
128*4d7e907cSAndroid Build Coastguard Worker __attribute__((__unused__))) const {
129*4d7e907cSAndroid Build Coastguard Worker ::android::audio_utils::lock_guard l(mCbMutex);
130*4d7e907cSAndroid Build Coastguard Worker if (!mAudioDevice.has_value()) {
131*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << __func__ << ": Momentary exposure without a registered device";
132*4d7e907cSAndroid Build Coastguard Worker return;
133*4d7e907cSAndroid Build Coastguard Worker }
134*4d7e907cSAndroid Build Coastguard Worker if (mCallback == nullptr) {
135*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": Momentary exposure without a registered callback";
136*4d7e907cSAndroid Build Coastguard Worker return;
137*4d7e907cSAndroid Build Coastguard Worker }
138*4d7e907cSAndroid Build Coastguard Worker
139*4d7e907cSAndroid Build Coastguard Worker mCallback->onMomentaryExposureWarning(currentMel, mAudioDevice.value());
140*4d7e907cSAndroid Build Coastguard Worker }
141*4d7e907cSAndroid Build Coastguard Worker
onMomentaryExposure(float currentMel,audio_port_handle_t deviceId) const142*4d7e907cSAndroid Build Coastguard Worker void SoundDose::MelCallback::onMomentaryExposure(float currentMel, audio_port_handle_t deviceId
143*4d7e907cSAndroid Build Coastguard Worker __attribute__((__unused__))) const {
144*4d7e907cSAndroid Build Coastguard Worker mSoundDose.onMomentaryExposure(currentMel, deviceId);
145*4d7e907cSAndroid Build Coastguard Worker }
146*4d7e907cSAndroid Build Coastguard Worker
147*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl::android::hardware::audio::core::sounddose
148