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 #ifndef INCLUDING_FROM_AUDIOFLINGER_H 19 #error This header file should only be included from AudioFlinger.h 20 #endif 21 22 #include <mutex> 23 #include <sounddose/SoundDoseManager.h> 24 #include <unordered_map> 25 26 constexpr static int kMaxTimestampDeltaInSec = 120; 27 28 /** 29 * Class for listening to new patches and starting the MEL computation. MelReporter is 30 * concealed within AudioFlinger, their lifetimes are the same. 31 */ 32 class MelReporter : public PatchCommandThread::PatchCommandListener, 33 public IMelReporterCallback { 34 public: MelReporter(AudioFlinger & audioFlinger)35 explicit MelReporter(AudioFlinger& audioFlinger) 36 : mAudioFlinger(audioFlinger) {} 37 38 void onFirstRef() override; 39 40 /** 41 * Activates the MEL reporting from the HAL sound dose interface. If the HAL 42 * does not support the sound dose interface for this module, the internal MEL 43 * calculation will be use. 44 * 45 * <p>If the device is using the audio AIDL HAL then this method will try to get the sound 46 * dose interface from IModule#getSoundDose(). Otherwise, if the legacy audio HIDL HAL is used 47 * this method will be looking for the standalone sound dose implementation. It falls back to 48 * the internal MEL computation if no valid sound dose interface can be retrieved. 49 * 50 * @return true if the MEL reporting will be done from any sound dose HAL interface 51 * implementation, false otherwise. 52 */ 53 bool activateHalSoundDoseComputation(const std::string& module, 54 const sp<DeviceHalInterface>& device); 55 56 /** 57 * Activates the MEL reporting from internal framework values. These are used 58 * as a fallback when there is no sound dose interface implementation from HAL. 59 * Note: the internal CSD computation does not guarantee a certification with 60 * IEC62368-1 3rd edition or EN50332-3 61 */ 62 void activateInternalSoundDoseComputation(); 63 64 sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback); 65 66 std::string dump(); 67 68 // IMelReporterCallback methods 69 void stopMelComputationForDeviceId(audio_port_handle_t deviceId) override; 70 void startMelComputationForDeviceId(audio_port_handle_t deviceId) override; 71 72 // PatchCommandListener methods 73 void onCreateAudioPatch(audio_patch_handle_t handle, 74 const PatchPanel::Patch& patch) override; 75 void onReleaseAudioPatch(audio_patch_handle_t handle) override; 76 77 /** 78 * The new metadata can determine whether we should compute MEL for the given thread. 79 * This is the case only if one of the tracks in the thread mix is using MEDIA or GAME. 80 * Otherwise, this method will disable CSD. 81 **/ 82 void updateMetadataForCsd(audio_io_handle_t streamHandle, 83 const std::vector<playback_track_metadata_v7_t>& metadataVec); 84 private: 85 struct ActiveMelPatch { 86 audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE}; 87 /** 88 * Stores device ids and whether they are compatible for CSD calculation. 89 * The boolean value can change since BT audio device types are user-configurable 90 * to headphones/headsets or other device types. 91 */ 92 std::vector<std::pair<audio_port_handle_t,bool>> deviceStates; 93 bool csdActive; 94 }; 95 96 void stopInternalMelComputation(); 97 98 /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */ 99 void stopMelComputationForPatch_l(const ActiveMelPatch& patch) REQUIRES(mLock); 100 101 /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */ 102 void startMelComputationForActivePatch_l(const ActiveMelPatch& patch) REQUIRES(mLock); 103 104 std::optional<audio_patch_handle_t> 105 activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mLock); 106 107 bool useHalSoundDoseInterface_l() REQUIRES(mLock); 108 109 AudioFlinger& mAudioFlinger; // does not own the object 110 111 sp<SoundDoseManager> mSoundDoseManager; 112 113 /** 114 * Lock for protecting the active mel patches. Do not mix with the AudioFlinger lock. 115 * Locking order AudioFlinger::mLock -> PatchCommandThread::mLock -> MelReporter::mLock. 116 */ 117 std::mutex mLock; 118 std::unordered_map<audio_patch_handle_t, ActiveMelPatch> 119 mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock); 120 std::unordered_map<audio_port_handle_t, int> 121 mActiveDevices GUARDED_BY(AudioFlinger::MelReporter::mLock); 122 bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false; 123 }; 124