1 /* 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 #pragma once 19 20 #include <aidl/android/hardware/audio/core/sounddose/ISoundDose.h> 21 #include <aidl/android/media/audio/common/AudioDevice.h> 22 #include <android/media/BnSoundDose.h> 23 #include <android/media/ISoundDoseCallback.h> 24 #include <media/AudioDeviceTypeAddr.h> 25 #include <audio_utils/MelAggregator.h> 26 #include <audio_utils/MelProcessor.h> 27 #include <binder/Status.h> 28 #include <mutex> 29 #include <unordered_map> 30 31 namespace android { 32 33 using aidl::android::hardware::audio::core::sounddose::ISoundDose; 34 35 class IMelReporterCallback : public virtual RefBase { 36 public: IMelReporterCallback()37 IMelReporterCallback() {}; ~IMelReporterCallback()38 virtual ~IMelReporterCallback() {}; 39 40 virtual void stopMelComputationForDeviceId(audio_port_handle_t deviceId) = 0; 41 virtual void startMelComputationForDeviceId(audio_port_handle_t deviceId) = 0; 42 }; 43 44 class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { 45 public: 46 /** CSD is computed with a rolling window of 7 days. */ 47 static constexpr int64_t kCsdWindowSeconds = 604800; // 60s * 60m * 24h * 7d 48 /** Default RS2 upper bound in dBA as defined in IEC 62368-1 3rd edition. */ 49 static constexpr float kDefaultRs2UpperBound = 100.f; 50 SoundDoseManager(const sp<IMelReporterCallback> & melReporterCallback)51 explicit SoundDoseManager(const sp<IMelReporterCallback>& melReporterCallback) 52 : mMelReporterCallback(melReporterCallback), 53 mMelAggregator(sp<audio_utils::MelAggregator>::make(kCsdWindowSeconds)), 54 mRs2UpperBound(kDefaultRs2UpperBound) {}; 55 56 /** 57 * \brief Creates or gets the MelProcessor assigned to the streamHandle 58 * 59 * \param deviceId id for the devices where the stream is active. 60 * \param streamHandle handle to the stream 61 * \param sampleRate sample rate for the processor 62 * \param channelCount number of channels to be processed. 63 * \param format format of the input samples. 64 * 65 * \return MelProcessor assigned to the stream and device id. 66 */ 67 sp<audio_utils::MelProcessor> getOrCreateProcessorForDevice(audio_port_handle_t deviceId, 68 audio_io_handle_t streamHandle, 69 uint32_t sampleRate, 70 size_t channelCount, 71 audio_format_t format); 72 73 /** 74 * \brief Removes stream processor when MEL computation is not needed anymore 75 * 76 * \param streamHandle handle to the stream 77 */ 78 void removeStreamProcessor(audio_io_handle_t streamHandle); 79 80 /** 81 * Sets the output RS2 upper bound for momentary exposure warnings. Must not be 82 * higher than 100dBA and not lower than 80dBA. 83 * 84 * \param rs2Value value to use for momentary exposure 85 */ 86 void setOutputRs2UpperBound(float rs2Value); 87 88 /** 89 * \brief Registers the interface for passing callbacks to the AudioService and gets 90 * the ISoundDose interface. 91 * 92 * \returns the sound dose binder to send commands to the SoundDoseManager 93 **/ 94 sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback); 95 96 /** 97 * Sets the HAL sound dose interface for a specific module to use for the MEL computation. 98 * 99 * @return true if setting the HAL sound dose value was successful, false otherwise. 100 */ 101 bool setHalSoundDoseInterface(const std::string &module, 102 const std::shared_ptr<ISoundDose> &halSoundDose); 103 104 /** Reset all the stored HAL sound dose interface. */ 105 void resetHalSoundDoseInterfaces(); 106 107 /** Returns the cached audio port id from the active devices. */ 108 audio_port_handle_t getIdForAudioDevice( 109 const aidl::android::media::audio::common::AudioDevice& audioDevice) const; 110 111 /** Caches mapping between address, device port id and device type. */ 112 void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt, const audio_port_handle_t deviceId); 113 114 /** Clear all map entries with passed audio_port_handle_t. */ 115 void clearMapDeviceIdEntries(audio_port_handle_t deviceId); 116 117 /** Returns true if CSD is enabled. */ 118 bool isCsdEnabled(); 119 120 void initCachedAudioDeviceCategories( 121 const std::vector<media::ISoundDose::AudioDeviceCategory>& deviceCategories); 122 123 void setAudioDeviceCategory( 124 const media::ISoundDose::AudioDeviceCategory& audioDevice); 125 126 /** 127 * Returns true if the type can compute CSD. For bluetooth devices we rely on whether we 128 * categorized the address as headphones/headsets, only in this case we return true. 129 */ 130 bool shouldComputeCsdForDeviceWithAddress(const audio_devices_t type, 131 const std::string& deviceAddress); 132 /** Returns true for all device types which could support CSD computation. */ 133 bool shouldComputeCsdForDeviceType(audio_devices_t device); 134 135 std::string dump() const; 136 137 // used for testing only 138 size_t getCachedMelRecordsSize() const; 139 bool forceUseFrameworkMel() const; 140 bool forceComputeCsdOnAllDevices() const; 141 142 /** Method for converting from audio_utils::CsdRecord to media::SoundDoseRecord. */ 143 static media::SoundDoseRecord csdRecordToSoundDoseRecord(const audio_utils::CsdRecord& legacy); 144 145 // ------ Override audio_utils::MelProcessor::MelCallback ------ 146 void onNewMelValues(const std::vector<float>& mels, size_t offset, size_t length, 147 audio_port_handle_t deviceId) const override; 148 149 void onMomentaryExposure(float currentMel, audio_port_handle_t deviceId) const override; 150 151 private: 152 class SoundDose : public media::BnSoundDose, 153 public IBinder::DeathRecipient { 154 public: SoundDose(SoundDoseManager * manager,const sp<media::ISoundDoseCallback> & callback)155 SoundDose(SoundDoseManager* manager, const sp<media::ISoundDoseCallback>& callback) 156 : mSoundDoseManager(manager), 157 mSoundDoseCallback(callback) {} 158 159 /** IBinder::DeathRecipient. Listen to the death of ISoundDoseCallback. */ 160 virtual void binderDied(const wp<IBinder>& who); 161 162 /** BnSoundDose override */ 163 binder::Status setOutputRs2UpperBound(float value) override; 164 binder::Status resetCsd(float currentCsd, 165 const std::vector<media::SoundDoseRecord>& records) override; 166 binder::Status updateAttenuation(float attenuationDB, int device) override; 167 binder::Status getOutputRs2UpperBound(float* value) override; 168 binder::Status setCsdEnabled(bool enabled) override; 169 170 binder::Status initCachedAudioDeviceCategories( 171 const std::vector<media::ISoundDose::AudioDeviceCategory> &btDeviceCategories) 172 override; 173 174 binder::Status setAudioDeviceCategory( 175 const media::ISoundDose::AudioDeviceCategory& btAudioDevice) override; 176 177 binder::Status getCsd(float* value) override; 178 binder::Status forceUseFrameworkMel(bool useFrameworkMel) override; 179 binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices) override; 180 binder::Status isSoundDoseHalSupported(bool* value) override; 181 182 wp<SoundDoseManager> mSoundDoseManager; 183 const sp<media::ISoundDoseCallback> mSoundDoseCallback; 184 }; 185 186 class HalSoundDoseCallback : public ISoundDose::BnHalSoundDoseCallback { 187 public: HalSoundDoseCallback(SoundDoseManager * manager)188 explicit HalSoundDoseCallback(SoundDoseManager* manager) 189 : mSoundDoseManager(manager) {} 190 191 ndk::ScopedAStatus onMomentaryExposureWarning( 192 float in_currentDbA, 193 const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override; 194 ndk::ScopedAStatus onNewMelValues( 195 const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord, 196 const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override; 197 198 wp<SoundDoseManager> mSoundDoseManager; 199 std::mutex mCbLock; 200 }; 201 202 void resetSoundDose(); 203 204 void resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records); 205 206 sp<media::ISoundDoseCallback> getSoundDoseCallback() const; 207 208 void updateAttenuation(float attenuationDB, audio_devices_t deviceType); 209 void setCsdEnabled(bool enabled); 210 void setUseFrameworkMel(bool useFrameworkMel); 211 void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices); 212 bool isSoundDoseHalSupported() const; 213 /** 214 * Returns true if there is one active HAL sound dose interface or null if internal MEL 215 * computation is used. 216 **/ 217 bool useHalSoundDose() const; 218 219 mutable std::mutex mLock; 220 221 const sp<IMelReporterCallback> mMelReporterCallback; 222 223 // no need for lock since MelAggregator is thread-safe 224 const sp<audio_utils::MelAggregator> mMelAggregator; 225 226 std::unordered_map<audio_io_handle_t, wp<audio_utils::MelProcessor>> mActiveProcessors 227 GUARDED_BY(mLock); 228 229 // map active device address and type to device id, used also for managing the pause/resume 230 // logic for deviceId's that should not report MEL values (e.g.: do not have an active MUSIC 231 // or GAME stream). 232 std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock); 233 std::unordered_map<audio_port_handle_t, audio_devices_t> mActiveDeviceTypes GUARDED_BY(mLock); 234 235 struct bt_device_type_hash { operatorbt_device_type_hash236 std::size_t operator() (const std::pair<std::string, audio_devices_t> &deviceType) const { 237 return std::hash<std::string>()(deviceType.first) ^ 238 std::hash<audio_devices_t>()(deviceType.second); 239 } 240 }; 241 // storing the BT cached information as received from the java side 242 // see SoundDoseManager::setCachedAudioDeviceCategories 243 std::unordered_map<std::pair<std::string, audio_devices_t>, bool, bt_device_type_hash> 244 mBluetoothDevicesWithCsd GUARDED_BY(mLock); 245 246 float mRs2UpperBound GUARDED_BY(mLock); 247 std::unordered_map<audio_devices_t, float> mMelAttenuationDB GUARDED_BY(mLock); 248 249 sp<SoundDose> mSoundDose GUARDED_BY(mLock); 250 251 std::unordered_map<std::string, std::shared_ptr<ISoundDose>> mHalSoundDose GUARDED_BY(mLock); 252 std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock); 253 254 bool mUseFrameworkMel GUARDED_BY(mLock) = false; 255 bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false; 256 257 bool mEnabledCsd GUARDED_BY(mLock) = true; 258 }; 259 260 } // namespace android 261