1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #include "AudioToken.h"
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AudioPowerManager"
19*ec779b8eSAndroid Build Coastguard Worker #include <com_android_media_audioserver.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <psh_utils/AudioPowerManager.h>
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker namespace android::media::psh_utils {
25*ec779b8eSAndroid Build Coastguard Worker
26*ec779b8eSAndroid Build Coastguard Worker /* static */
getAudioPowerManager()27*ec779b8eSAndroid Build Coastguard Worker AudioPowerManager& AudioPowerManager::getAudioPowerManager() {
28*ec779b8eSAndroid Build Coastguard Worker [[clang::no_destroy]] static AudioPowerManager apm;
29*ec779b8eSAndroid Build Coastguard Worker return apm;
30*ec779b8eSAndroid Build Coastguard Worker }
31*ec779b8eSAndroid Build Coastguard Worker
startClient(pid_t pid,uid_t uid,const std::string & additional)32*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<Token> AudioPowerManager::startClient(pid_t pid, uid_t uid,
33*ec779b8eSAndroid Build Coastguard Worker const std::string& additional) {
34*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<PowerClientStats> powerClientStats;
35*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mMutex);
36*ec779b8eSAndroid Build Coastguard Worker if (mPowerClientStats.count(uid) == 0) {
37*ec779b8eSAndroid Build Coastguard Worker const auto it = mHistoricalClients.find(uid);
38*ec779b8eSAndroid Build Coastguard Worker if (it == mHistoricalClients.end()) {
39*ec779b8eSAndroid Build Coastguard Worker powerClientStats = std::make_shared<PowerClientStats>(uid, additional);
40*ec779b8eSAndroid Build Coastguard Worker } else {
41*ec779b8eSAndroid Build Coastguard Worker powerClientStats = it->second;
42*ec779b8eSAndroid Build Coastguard Worker mHistoricalClients.erase(it);
43*ec779b8eSAndroid Build Coastguard Worker }
44*ec779b8eSAndroid Build Coastguard Worker mPowerClientStats[uid] = powerClientStats;
45*ec779b8eSAndroid Build Coastguard Worker } else {
46*ec779b8eSAndroid Build Coastguard Worker powerClientStats = mPowerClientStats[uid];
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker powerClientStats->addPid(pid);
49*ec779b8eSAndroid Build Coastguard Worker mPidToUid[pid] = uid;
50*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<Token> token =
51*ec779b8eSAndroid Build Coastguard Worker std::make_unique<AudioClientToken>(powerClientStats, pid, uid, additional);
52*ec779b8eSAndroid Build Coastguard Worker mOutstandingTokens.emplace(token.get());
53*ec779b8eSAndroid Build Coastguard Worker return token;
54*ec779b8eSAndroid Build Coastguard Worker }
55*ec779b8eSAndroid Build Coastguard Worker
startTrack(uid_t uid,const std::string & additional)56*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<Token> AudioPowerManager::startTrack(uid_t uid, const std::string& additional) {
57*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mMutex);
58*ec779b8eSAndroid Build Coastguard Worker if (mPowerClientStats.count(uid) == 0) {
59*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: Cannot find uid: %d", __func__, uid);
60*ec779b8eSAndroid Build Coastguard Worker return {};
61*ec779b8eSAndroid Build Coastguard Worker }
62*ec779b8eSAndroid Build Coastguard Worker auto powerClientStats = mPowerClientStats[uid];
63*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<Token> token =
64*ec779b8eSAndroid Build Coastguard Worker std::make_unique<AudioTrackToken>(powerClientStats, additional);
65*ec779b8eSAndroid Build Coastguard Worker mOutstandingTokens.emplace(token.get());
66*ec779b8eSAndroid Build Coastguard Worker return token;
67*ec779b8eSAndroid Build Coastguard Worker }
68*ec779b8eSAndroid Build Coastguard Worker
startThread(pid_t pid,const std::string & wakeLockName,WakeFlag wakeFlag,const std::string & additional)69*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<Token> AudioPowerManager::startThread(
70*ec779b8eSAndroid Build Coastguard Worker pid_t pid, const std::string& wakeLockName,
71*ec779b8eSAndroid Build Coastguard Worker WakeFlag wakeFlag, const std::string& additional) {
72*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mMutex);
73*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<Token> token =
74*ec779b8eSAndroid Build Coastguard Worker std::make_unique<AudioThreadToken>(pid, wakeLockName, wakeFlag, additional);
75*ec779b8eSAndroid Build Coastguard Worker mOutstandingTokens.emplace(token.get());
76*ec779b8eSAndroid Build Coastguard Worker return token;
77*ec779b8eSAndroid Build Coastguard Worker }
78*ec779b8eSAndroid Build Coastguard Worker
toString() const79*ec779b8eSAndroid Build Coastguard Worker std::string AudioPowerManager::toString() const {
80*ec779b8eSAndroid Build Coastguard Worker const std::string prefix(" ");
81*ec779b8eSAndroid Build Coastguard Worker std::string result;
82*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mMutex);
83*ec779b8eSAndroid Build Coastguard Worker result.append("Power Tokens:\n");
84*ec779b8eSAndroid Build Coastguard Worker std::vector<std::string> tokenInfo;
85*ec779b8eSAndroid Build Coastguard Worker for (const auto& token: mOutstandingTokens) {
86*ec779b8eSAndroid Build Coastguard Worker tokenInfo.emplace_back(token->toString());
87*ec779b8eSAndroid Build Coastguard Worker }
88*ec779b8eSAndroid Build Coastguard Worker std::sort(tokenInfo.begin(), tokenInfo.end());
89*ec779b8eSAndroid Build Coastguard Worker for (const auto& info: tokenInfo) {
90*ec779b8eSAndroid Build Coastguard Worker result.append(prefix).append(info).append("\n");
91*ec779b8eSAndroid Build Coastguard Worker }
92*ec779b8eSAndroid Build Coastguard Worker result.append("Power Clients:\n");
93*ec779b8eSAndroid Build Coastguard Worker for (const auto& [uid, powerClientStats]: mPowerClientStats) {
94*ec779b8eSAndroid Build Coastguard Worker result.append(powerClientStats->toString(true, prefix));
95*ec779b8eSAndroid Build Coastguard Worker }
96*ec779b8eSAndroid Build Coastguard Worker result.append("Power Client History:\n");
97*ec779b8eSAndroid Build Coastguard Worker for (const auto& [power, powerClientStats]: mHistoricalClients) {
98*ec779b8eSAndroid Build Coastguard Worker result.append(powerClientStats->toString(true, prefix));
99*ec779b8eSAndroid Build Coastguard Worker }
100*ec779b8eSAndroid Build Coastguard Worker return result;
101*ec779b8eSAndroid Build Coastguard Worker }
102*ec779b8eSAndroid Build Coastguard Worker
stopClient(pid_t pid)103*ec779b8eSAndroid Build Coastguard Worker void AudioPowerManager::stopClient(pid_t pid) {
104*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mMutex);
105*ec779b8eSAndroid Build Coastguard Worker const auto pidit = mPidToUid.find(pid);
106*ec779b8eSAndroid Build Coastguard Worker if (pidit == mPidToUid.end()) return;
107*ec779b8eSAndroid Build Coastguard Worker const uid_t uid = pidit->second;
108*ec779b8eSAndroid Build Coastguard Worker const auto it = mPowerClientStats.find(uid);
109*ec779b8eSAndroid Build Coastguard Worker if (it == mPowerClientStats.end()) return;
110*ec779b8eSAndroid Build Coastguard Worker
111*ec779b8eSAndroid Build Coastguard Worker auto powerClientStats = it->second;
112*ec779b8eSAndroid Build Coastguard Worker size_t count = powerClientStats->removePid(pid);
113*ec779b8eSAndroid Build Coastguard Worker if (count == 0) {
114*ec779b8eSAndroid Build Coastguard Worker mHistoricalClients[uid] = powerClientStats;
115*ec779b8eSAndroid Build Coastguard Worker mPowerClientStats.erase(it);
116*ec779b8eSAndroid Build Coastguard Worker if (mHistoricalClients.size() > kHistory) {
117*ec779b8eSAndroid Build Coastguard Worker mHistoricalClients.erase(mHistoricalClients.begin()); // remove oldest.
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker }
120*ec779b8eSAndroid Build Coastguard Worker mPidToUid.erase(pid);
121*ec779b8eSAndroid Build Coastguard Worker }
122*ec779b8eSAndroid Build Coastguard Worker
clear_token_ptr(Token * token)123*ec779b8eSAndroid Build Coastguard Worker void AudioPowerManager::clear_token_ptr(Token* token) {
124*ec779b8eSAndroid Build Coastguard Worker if (token != nullptr) {
125*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mMutex);
126*ec779b8eSAndroid Build Coastguard Worker (void)mOutstandingTokens.erase(token);
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker
130*ec779b8eSAndroid Build Coastguard Worker /* static */
enabled()131*ec779b8eSAndroid Build Coastguard Worker bool AudioPowerManager::enabled() {
132*ec779b8eSAndroid Build Coastguard Worker static const bool enabled = com::android::media::audioserver::power_stats()
133*ec779b8eSAndroid Build Coastguard Worker && property_get_bool("persist.audio.power_stats.enabled", false);
134*ec779b8eSAndroid Build Coastguard Worker return enabled;
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker
137*ec779b8eSAndroid Build Coastguard Worker } // namespace android::media::psh_utils
138