blob: 8cc7eabcb50744e9983b2b0abfb82c0eeb384c00 [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) {
30 switch (device) {
31 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
32 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
33 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
34 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
35 case AUDIO_DEVICE_OUT_HEARING_AID:
36 case AUDIO_DEVICE_OUT_USB_HEADSET:
37 case AUDIO_DEVICE_OUT_BLE_HEADSET:
38 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
39 return true;
40 default:
41 return false;
42 }
43}
44
45void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
46 const PatchPanel::Patch& patch) {
47 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
48 __func__, handle, patch.mHalHandle,
49 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
50 if (patch.mAudioPatch.num_sources == 0
51 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
52 ALOGW("%s: patch does not contain any mix sources", __func__);
53 return;
54 }
55
56 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
57 ActiveMelPatch newPatch;
58 newPatch.streamHandle = streamHandle;
59 for (int i = 0; i < patch.mAudioPatch.num_sinks; ++ i) {
60 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
61 && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
62 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
63 newPatch.deviceHandles.push_back(deviceId);
64
65 // Start the MEL calculation in the PlaybackThread
66 std::lock_guard _lAf(mAudioFlinger.mLock);
67 auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
68 if (thread != nullptr) {
Vlad Popaf09e93f2022-10-31 16:27:12 +010069 thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
Vlad Popab042ee62022-10-20 18:05:00 +020070 deviceId,
Vlad Popaf09e93f2022-10-31 16:27:12 +010071 newPatch.streamHandle,
72 thread->mSampleRate,
73 thread->mChannelCount,
74 thread->mFormat));
Vlad Popab042ee62022-10-20 18:05:00 +020075 }
76 }
77 }
78
79 std::lock_guard _l(mLock);
80 mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
81}
82
83void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
84 ALOGV("%s", __func__);
85
86 ActiveMelPatch melPatch;
87 {
88 std::lock_guard _l(mLock);
89
90 auto patchIt = mActiveMelPatches.find(handle);
91 if (patchIt == mActiveMelPatches.end()) {
92 ALOGW(
93 "%s patch does not contain any mix sources with active MEL calculation",
94 __func__);
95 return;
96 }
97
98 melPatch = patchIt->second;
99 mActiveMelPatches.erase(patchIt);
100 }
101
102 // Stop MEL calculation for the PlaybackThread
103 std::lock_guard _lAf(mAudioFlinger.mLock);
Vlad Popaf09e93f2022-10-31 16:27:12 +0100104 mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle);
Vlad Popab042ee62022-10-20 18:05:00 +0200105 auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
106 if (thread != nullptr) {
107 thread->stopMelComputation();
108 }
Vlad Popab042ee62022-10-20 18:05:00 +0200109}
110
Vlad Popae3fd1c22022-11-07 21:03:18 +0100111sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
Vlad Popa63f047e2022-11-05 14:09:19 +0100112 const sp<media::ISoundDoseCallback>& callback) {
Vlad Popae3fd1c22022-11-07 21:03:18 +0100113 // no need to lock since getSoundDoseInterface is synchronized
114 return mSoundDoseManager.getSoundDoseInterface(callback);
Vlad Popa63f047e2022-11-05 14:09:19 +0100115}
116
Vlad Popab042ee62022-10-20 18:05:00 +0200117std::string AudioFlinger::MelReporter::dump() {
118 std::lock_guard _l(mLock);
Vlad Popa2900c0a2022-10-24 13:38:00 +0200119 std::string output("\nSound Dose:\n");
120 output.append(mSoundDoseManager.dump());
Vlad Popab042ee62022-10-20 18:05:00 +0200121 return output;
122}
123
124} // namespace android