xref: /aosp_15_r20/frameworks/av/media/psh_utils/PowerStatsCollector.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <android-base/logging.h>
17 #include <psh_utils/PowerStatsCollector.h>
18 #include "PowerStatsProvider.h"
19 #include <utils/Timers.h>
20 
21 namespace android::media::psh_utils {
22 
PowerStatsCollector()23 PowerStatsCollector::PowerStatsCollector() {
24     addProvider(std::make_unique<PowerEntityResidencyDataProvider>());
25     addProvider(std::make_unique<RailEnergyDataProvider>());
26     addProvider(std::make_unique<HealthStatsDataProvider>());
27 }
28 
29 /* static */
getCollector()30 PowerStatsCollector& PowerStatsCollector::getCollector() {
31     [[clang::no_destroy]] static PowerStatsCollector psc;
32     return psc;
33 }
34 
getStats(int64_t toleranceNs)35 std::shared_ptr<const PowerStats> PowerStatsCollector::getStats(int64_t toleranceNs) {
36     // Check if there is a cached PowerStats result available.
37     // As toleranceNs may be different between callers, it may be that some callers
38     // are blocked on mMutexExclusiveFill for a new stats result, while other callers
39     // may find the current cached result acceptable (within toleranceNs).
40     if (toleranceNs > 0) {
41         auto result = checkLastStats(toleranceNs);
42         if (result) return result;
43     }
44 
45     // Take the mMutexExclusiveFill to ensure only one thread is filling.
46     std::lock_guard lg1(mMutexExclusiveFill);
47     // As obtaining a new PowerStats snapshot might take some time,
48     // check again to see if another waiting thread filled the cached result for us.
49     if (toleranceNs > 0) {
50         auto result = checkLastStats(toleranceNs);
51         if (result) return result;
52     }
53     auto result = std::make_shared<PowerStats>();
54     (void)fill(result.get());
55     std::lock_guard lg2(mMutex);
56     mLastFetchNs = systemTime(SYSTEM_TIME_BOOTTIME);
57     mLastFetchStats = result;
58     return result;
59 }
60 
checkLastStats(int64_t toleranceNs) const61 std::shared_ptr<const PowerStats> PowerStatsCollector::checkLastStats(int64_t toleranceNs) const {
62     if (toleranceNs > 0) {
63         // see if we can return an old result.
64         std::lock_guard lg(mMutex);
65         if (mLastFetchStats && systemTime(SYSTEM_TIME_BOOTTIME) - mLastFetchNs < toleranceNs) {
66             return mLastFetchStats;
67         }
68     }
69     return {};
70 }
71 
addProvider(std::unique_ptr<PowerStatsProvider> && powerStatsProvider)72 void PowerStatsCollector::addProvider(std::unique_ptr<PowerStatsProvider>&& powerStatsProvider) {
73     mPowerStatsProviders.emplace_back(std::move(powerStatsProvider));
74 }
75 
fill(PowerStats * stats) const76 int PowerStatsCollector::fill(PowerStats* stats) const {
77     if (!stats) {
78         LOG(ERROR) << __func__ << ": bad args; stat is null";
79         return 1;
80     }
81 
82     for (const auto& provider : mPowerStatsProviders) {
83         (void) provider->fill(stats); // on error, we continue to proceed.
84     }
85 
86     // boot time follows wall clock time, but starts from boot.
87     stats->metadata.start_time_since_boot_ms = systemTime(SYSTEM_TIME_BOOTTIME) / 1'000'000;
88 
89     // wall clock time
90     stats->metadata.start_time_epoch_ms = systemTime(SYSTEM_TIME_REALTIME) / 1'000'000;
91 
92     // monotonic time follows boot time, but does not include any time suspended.
93     stats->metadata.start_time_monotonic_ms = systemTime() / 1'000'000;
94     return 0;
95 }
96 
97 } // namespace android::media::psh_utils
98