blob: 3ae681ad45cfeee017cda247d9053fac6b1a5088 [file] [log] [blame]
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "AudioToken.h"
#define LOG_TAG "AudioPowerManager"
#include <com_android_media_audioserver.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <psh_utils/AudioPowerManager.h>
namespace android::media::psh_utils {
/* static */
AudioPowerManager& AudioPowerManager::getAudioPowerManager() {
[[clang::no_destroy]] static AudioPowerManager apm;
return apm;
}
std::unique_ptr<Token> AudioPowerManager::startClient(pid_t pid, uid_t uid,
const std::string& additional) {
std::shared_ptr<PowerClientStats> powerClientStats;
std::lock_guard l(mMutex);
if (mPowerClientStats.count(uid) == 0) {
const auto it = mHistoricalClients.find(uid);
if (it == mHistoricalClients.end()) {
powerClientStats = std::make_shared<PowerClientStats>(uid, additional);
} else {
powerClientStats = it->second;
mHistoricalClients.erase(it);
}
mPowerClientStats[uid] = powerClientStats;
} else {
powerClientStats = mPowerClientStats[uid];
}
powerClientStats->addPid(pid);
mPidToUid[pid] = uid;
std::unique_ptr<Token> token =
std::make_unique<AudioClientToken>(powerClientStats, pid, uid, additional);
mOutstandingTokens.emplace(token.get());
return token;
}
std::unique_ptr<Token> AudioPowerManager::startTrack(uid_t uid, const std::string& additional) {
std::lock_guard l(mMutex);
if (mPowerClientStats.count(uid) == 0) {
ALOGW("%s: Cannot find uid: %d", __func__, uid);
return {};
}
auto powerClientStats = mPowerClientStats[uid];
std::unique_ptr<Token> token =
std::make_unique<AudioTrackToken>(powerClientStats, additional);
mOutstandingTokens.emplace(token.get());
return token;
}
std::unique_ptr<Token> AudioPowerManager::startThread(
pid_t pid, const std::string& wakeLockName,
WakeFlag wakeFlag, const std::string& additional) {
std::lock_guard l(mMutex);
std::unique_ptr<Token> token =
std::make_unique<AudioThreadToken>(pid, wakeLockName, wakeFlag, additional);
mOutstandingTokens.emplace(token.get());
return token;
}
std::string AudioPowerManager::toString() const {
const std::string prefix(" ");
std::string result;
std::lock_guard l(mMutex);
result.append("Power Tokens:\n");
std::vector<std::string> tokenInfo;
for (const auto& token: mOutstandingTokens) {
tokenInfo.emplace_back(token->toString());
}
std::sort(tokenInfo.begin(), tokenInfo.end());
for (const auto& info: tokenInfo) {
result.append(prefix).append(info).append("\n");
}
result.append("Power Clients:\n");
for (const auto& [uid, powerClientStats]: mPowerClientStats) {
result.append(powerClientStats->toString(true, prefix));
}
result.append("Power Client History:\n");
for (const auto& [power, powerClientStats]: mHistoricalClients) {
result.append(powerClientStats->toString(true, prefix));
}
return result;
}
void AudioPowerManager::stopClient(pid_t pid) {
std::lock_guard l(mMutex);
const auto pidit = mPidToUid.find(pid);
if (pidit == mPidToUid.end()) return;
const uid_t uid = pidit->second;
const auto it = mPowerClientStats.find(uid);
if (it == mPowerClientStats.end()) return;
auto powerClientStats = it->second;
size_t count = powerClientStats->removePid(pid);
if (count == 0) {
mHistoricalClients[uid] = powerClientStats;
mPowerClientStats.erase(it);
if (mHistoricalClients.size() > kHistory) {
mHistoricalClients.erase(mHistoricalClients.begin()); // remove oldest.
}
}
mPidToUid.erase(pid);
}
void AudioPowerManager::clear_token_ptr(Token* token) {
if (token != nullptr) {
std::lock_guard l(mMutex);
(void)mOutstandingTokens.erase(token);
}
}
/* static */
bool AudioPowerManager::enabled() {
static const bool enabled = com::android::media::audioserver::power_stats()
&& property_get_bool("persist.audio.power_stats.enabled", false);
return enabled;
}
} // namespace android::media::psh_utils