blob: 9a579dd33a27c23609ec0da0d8068821a34fe7d4 [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
21#include <cinttypes>
22#include <utils/Log.h>
23#include <android-base/stringprintf.h>
24#include <audio_utils/power.h>
25
26#include "AudioFlinger.h"
27
28namespace android {
29
30bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
31 switch (device) {
32 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
33 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
34 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
35 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
36 case AUDIO_DEVICE_OUT_HEARING_AID:
37 case AUDIO_DEVICE_OUT_USB_HEADSET:
38 case AUDIO_DEVICE_OUT_BLE_HEADSET:
39 case AUDIO_DEVICE_OUT_BLE_BROADCAST:
40 return true;
41 default:
42 return false;
43 }
44}
45
46void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
47 const PatchPanel::Patch& patch) {
48 ALOGV("%s: handle %d mHalHandle %d device sink %08x",
49 __func__, handle, patch.mHalHandle,
50 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
51 if (patch.mAudioPatch.num_sources == 0
52 || patch.mAudioPatch.sources[0].type != AUDIO_PORT_TYPE_MIX) {
53 ALOGW("%s: patch does not contain any mix sources", __func__);
54 return;
55 }
56
57 audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle;
58 ActiveMelPatch newPatch;
59 newPatch.streamHandle = streamHandle;
60 for (int i = 0; i < patch.mAudioPatch.num_sinks; ++ i) {
61 if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE
62 && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
63 audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
64 newPatch.deviceHandles.push_back(deviceId);
65
66 // Start the MEL calculation in the PlaybackThread
67 std::lock_guard _lAf(mAudioFlinger.mLock);
68 auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
69 if (thread != nullptr) {
70 thread->startMelComputation(mMelAggregator.getOrCreateCallbackForDevice(
71 deviceId,
72 newPatch.streamHandle));
73 }
74 }
75 }
76
77 std::lock_guard _l(mLock);
78 mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
79}
80
81void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
82 ALOGV("%s", __func__);
83
84 ActiveMelPatch melPatch;
85 {
86 std::lock_guard _l(mLock);
87
88 auto patchIt = mActiveMelPatches.find(handle);
89 if (patchIt == mActiveMelPatches.end()) {
90 ALOGW(
91 "%s patch does not contain any mix sources with active MEL calculation",
92 __func__);
93 return;
94 }
95
96 melPatch = patchIt->second;
97 mActiveMelPatches.erase(patchIt);
98 }
99
100 // Stop MEL calculation for the PlaybackThread
101 std::lock_guard _lAf(mAudioFlinger.mLock);
102 auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
103 if (thread != nullptr) {
104 thread->stopMelComputation();
105 }
106 mMelAggregator.removeStreamCallback(melPatch.streamHandle);
107}
108
109std::string AudioFlinger::MelReporter::dump() {
110 std::lock_guard _l(mLock);
111 std::string output;
112
113 base::StringAppendF(&output, "\nMel Reporter:\n");
114 mMelAggregator.foreach([&output](const audio_utils::MelRecord& melRecord) {
115 base::StringAppendF(&output, "Continuous MELs for portId=%d, ", melRecord.portId);
116 base::StringAppendF(&output, "starting at timestamp %" PRId64 ": ", melRecord.timestamp);
117
118 for (const auto& mel : melRecord.mels) {
119 base::StringAppendF(&output, "%d ", mel);
120 }
121 base::StringAppendF(&output, "\n");
122 });
123
124 return output;
125}
126
127} // namespace android