blob: b2e80274c371a29771b1e274b9a7629349dfaf77 [file] [log] [blame]
Vlad Popab042ee62022-10-20 18:05: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 "AudioFlinger::MelReporter"
20
Vlad Popab042ee62022-10-20 18:05:00 +020021#include "AudioFlinger.h"
22
Vlad Popa63f047e2022-11-05 14:09:19 +010023#include <android/media/ISoundDoseCallback.h>
Vlad Popa2900c0a2022-10-24 13:38:00 +020024#include <audio_utils/power.h>
25#include <utils/Log.h>
26
Vlad Popab042ee62022-10-20 18:05:00 +020027namespace android {
28
29bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
Vlad Popa91930462022-12-20 22:42:48 +010030 if (mSoundDoseManager.computeCsdOnAllDevices()) {
31 return true;
32 }
33
Vlad Popab042ee62022-10-20 18:05:00 +020034 switch (device) {
35 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
36 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
37 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
38 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
39 case AUDIO_DEVICE_OUT_HEARING_AID:
40 case AUDIO_DEVICE_OUT_USB_HEADSET:
41 case AUDIO_DEVICE_OUT_BLE_HEADSET:
42 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
43 return true;
44 default:
45 return false;
46 }
47}
48
49void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
50 const PatchPanel::Patch& patch) {
51 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
52 __func__, handle, patch.mHalHandle,
53 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
54 if (patch.mAudioPatch.num_sources == 0
55 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
56 ALOGW("%s: patch does not contain any mix sources", __func__);
57 return;
58 }
59
60 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
61 ActiveMelPatch newPatch;
62 newPatch.streamHandle = streamHandle;
63 for (int i = 0; i < patch.mAudioPatch.num_sinks; ++ i) {
64 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
65 && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
66 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
67 newPatch.deviceHandles.push_back(deviceId);
68
69 // Start the MEL calculation in the PlaybackThread
70 std::lock_guard _lAf(mAudioFlinger.mLock);
71 auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
72 if (thread != nullptr) {
Vlad Popaf09e93f2022-10-31 16:27:12 +010073 thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
Vlad Popab042ee62022-10-20 18:05:00 +020074 deviceId,
Vlad Popaf09e93f2022-10-31 16:27:12 +010075 newPatch.streamHandle,
76 thread->mSampleRate,
77 thread->mChannelCount,
78 thread->mFormat));
Vlad Popab042ee62022-10-20 18:05:00 +020079 }
80 }
81 }
82
83 std::lock_guard _l(mLock);
84 mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
85}
86
87void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
88 ALOGV("%s", __func__);
89
90 ActiveMelPatch melPatch;
91 {
92 std::lock_guard _l(mLock);
93
94 auto patchIt = mActiveMelPatches.find(handle);
95 if (patchIt == mActiveMelPatches.end()) {
96 ALOGW(
97 "%s patch does not contain any mix sources with active MEL calculation",
98 __func__);
99 return;
100 }
101
102 melPatch = patchIt->second;
103 mActiveMelPatches.erase(patchIt);
104 }
105
106 // Stop MEL calculation for the PlaybackThread
107 std::lock_guard _lAf(mAudioFlinger.mLock);
Vlad Popaf09e93f2022-10-31 16:27:12 +0100108 mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle);
Vlad Popab042ee62022-10-20 18:05:00 +0200109 auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
110 if (thread != nullptr) {
111 thread->stopMelComputation();
112 }
Vlad Popab042ee62022-10-20 18:05:00 +0200113}
114
Vlad Popae3fd1c22022-11-07 21:03:18 +0100115sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100116 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100117 // no need to lock since getSoundDoseInterface is synchronized
118 return mSoundDoseManager.getSoundDoseInterface(callback);
Vlad Popa63f047e2022-11-05 14:09:19 +0100119}
120
Vlad Popab042ee62022-10-20 18:05:00 +0200121std::string AudioFlinger::MelReporter::dump() {
122 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200123 std::string output("\nSound Dose:\n");
124 output.append(mSoundDoseManager.dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200125 return output;
126}
127
128} // namespace android