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