/* * 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 #include #include #include namespace android::media::psh_utils { /* static */ AudioPowerManager& AudioPowerManager::getAudioPowerManager() { [[clang::no_destroy]] static AudioPowerManager apm; return apm; } std::unique_ptr AudioPowerManager::startClient(pid_t pid, uid_t uid, const std::string& additional) { std::shared_ptr 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(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 = std::make_unique(powerClientStats, pid, uid, additional); mOutstandingTokens.emplace(token.get()); return token; } std::unique_ptr 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 = std::make_unique(powerClientStats, additional); mOutstandingTokens.emplace(token.get()); return token; } std::unique_ptr AudioPowerManager::startThread( pid_t pid, const std::string& wakeLockName, WakeFlag wakeFlag, const std::string& additional) { std::lock_guard l(mMutex); std::unique_ptr token = std::make_unique(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 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