xref: /aosp_15_r20/frameworks/av/media/psh_utils/PowerStats.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 #include <android-base/logging.h>
17*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/clock.h>
18*ec779b8eSAndroid Build Coastguard Worker #include <psh_utils/PowerStats.h>
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker namespace android::media::psh_utils {
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker // Determine the best start time from a and b, which is
23*ec779b8eSAndroid Build Coastguard Worker // min(a, b) if both exist, otherwise the one that exists.
24*ec779b8eSAndroid Build Coastguard Worker template <typename T>
choose_best_start_time(const T & a,const T & b)25*ec779b8eSAndroid Build Coastguard Worker const T& choose_best_start_time(const T& a, const T& b) {
26*ec779b8eSAndroid Build Coastguard Worker     if (a) {
27*ec779b8eSAndroid Build Coastguard Worker         return b ? std::min(a, b) : a;
28*ec779b8eSAndroid Build Coastguard Worker     } else {
29*ec779b8eSAndroid Build Coastguard Worker         return b;
30*ec779b8eSAndroid Build Coastguard Worker     }
31*ec779b8eSAndroid Build Coastguard Worker }
32*ec779b8eSAndroid Build Coastguard Worker 
33*ec779b8eSAndroid Build Coastguard Worker // subtract two time differences.
34*ec779b8eSAndroid Build Coastguard Worker template <typename T, typename U>
sub_time_diff(const T & diff_a,const T & diff_b,const U & abs_c,const U & abs_d)35*ec779b8eSAndroid Build Coastguard Worker const T sub_time_diff(const T& diff_a, const T& diff_b, const U& abs_c, const U& abs_d) {
36*ec779b8eSAndroid Build Coastguard Worker     if (diff_a) {
37*ec779b8eSAndroid Build Coastguard Worker         return diff_b ? (diff_a - diff_b) : diff_a;
38*ec779b8eSAndroid Build Coastguard Worker     } else if (diff_b) {
39*ec779b8eSAndroid Build Coastguard Worker         return diff_b;
40*ec779b8eSAndroid Build Coastguard Worker     } else {  // no difference exists, use absolute time.
41*ec779b8eSAndroid Build Coastguard Worker         return abs_c - abs_d;
42*ec779b8eSAndroid Build Coastguard Worker     }
43*ec779b8eSAndroid Build Coastguard Worker }
44*ec779b8eSAndroid Build Coastguard Worker 
toString() const45*ec779b8eSAndroid Build Coastguard Worker std::string PowerStats::Metadata::toString() const {
46*ec779b8eSAndroid Build Coastguard Worker     return std::string("start_time_since_boot_ms: ").append(
47*ec779b8eSAndroid Build Coastguard Worker                     std::to_string(start_time_since_boot_ms))
48*ec779b8eSAndroid Build Coastguard Worker             .append(" start_time_monotonic_ms: ").append(std::to_string(start_time_monotonic_ms))
49*ec779b8eSAndroid Build Coastguard Worker             .append(audio_utils_time_string_from_ns(start_time_epoch_ms * 1'000'000).time)
50*ec779b8eSAndroid Build Coastguard Worker             .append(" duration_ms: ").append(std::to_string(duration_ms))
51*ec779b8eSAndroid Build Coastguard Worker             .append(" duration_monotonic_ms: ").append(std::to_string(duration_monotonic_ms));
52*ec779b8eSAndroid Build Coastguard Worker }
53*ec779b8eSAndroid Build Coastguard Worker 
operator +=(const Metadata & other)54*ec779b8eSAndroid Build Coastguard Worker PowerStats::Metadata PowerStats::Metadata::operator+=(const Metadata& other) {
55*ec779b8eSAndroid Build Coastguard Worker     start_time_since_boot_ms = choose_best_start_time(
56*ec779b8eSAndroid Build Coastguard Worker             start_time_since_boot_ms, other.start_time_since_boot_ms);
57*ec779b8eSAndroid Build Coastguard Worker     start_time_epoch_ms = choose_best_start_time(
58*ec779b8eSAndroid Build Coastguard Worker             start_time_epoch_ms, other.start_time_epoch_ms);
59*ec779b8eSAndroid Build Coastguard Worker     start_time_monotonic_ms = choose_best_start_time(
60*ec779b8eSAndroid Build Coastguard Worker             start_time_monotonic_ms, other.start_time_monotonic_ms);
61*ec779b8eSAndroid Build Coastguard Worker     duration_ms += other.duration_ms;
62*ec779b8eSAndroid Build Coastguard Worker     duration_monotonic_ms += other.duration_monotonic_ms;
63*ec779b8eSAndroid Build Coastguard Worker     return *this;
64*ec779b8eSAndroid Build Coastguard Worker }
65*ec779b8eSAndroid Build Coastguard Worker 
operator -=(const Metadata & other)66*ec779b8eSAndroid Build Coastguard Worker PowerStats::Metadata PowerStats::Metadata::operator-=(const Metadata& other) {
67*ec779b8eSAndroid Build Coastguard Worker     // here we calculate duration, if it makes sense.
68*ec779b8eSAndroid Build Coastguard Worker     duration_ms = sub_time_diff(duration_ms, other.duration_ms,
69*ec779b8eSAndroid Build Coastguard Worker                                 start_time_since_boot_ms, other.start_time_since_boot_ms);
70*ec779b8eSAndroid Build Coastguard Worker     duration_monotonic_ms = sub_time_diff(
71*ec779b8eSAndroid Build Coastguard Worker             duration_monotonic_ms, other.duration_monotonic_ms,
72*ec779b8eSAndroid Build Coastguard Worker             start_time_monotonic_ms, other.start_time_monotonic_ms);
73*ec779b8eSAndroid Build Coastguard Worker     start_time_since_boot_ms = choose_best_start_time(
74*ec779b8eSAndroid Build Coastguard Worker             start_time_since_boot_ms, other.start_time_since_boot_ms);
75*ec779b8eSAndroid Build Coastguard Worker     start_time_epoch_ms = choose_best_start_time(
76*ec779b8eSAndroid Build Coastguard Worker             start_time_epoch_ms, other.start_time_epoch_ms);
77*ec779b8eSAndroid Build Coastguard Worker     start_time_monotonic_ms = choose_best_start_time(
78*ec779b8eSAndroid Build Coastguard Worker             start_time_monotonic_ms, other.start_time_monotonic_ms);
79*ec779b8eSAndroid Build Coastguard Worker     return *this;
80*ec779b8eSAndroid Build Coastguard Worker }
81*ec779b8eSAndroid Build Coastguard Worker 
operator +(const Metadata & other) const82*ec779b8eSAndroid Build Coastguard Worker PowerStats::Metadata PowerStats::Metadata::operator+(const Metadata& other) const {
83*ec779b8eSAndroid Build Coastguard Worker     Metadata result = *this;
84*ec779b8eSAndroid Build Coastguard Worker     result += other;
85*ec779b8eSAndroid Build Coastguard Worker     return result;
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker 
operator -(const Metadata & other) const88*ec779b8eSAndroid Build Coastguard Worker PowerStats::Metadata PowerStats::Metadata::operator-(const Metadata& other) const {
89*ec779b8eSAndroid Build Coastguard Worker     Metadata result = *this;
90*ec779b8eSAndroid Build Coastguard Worker     result -= other;
91*ec779b8eSAndroid Build Coastguard Worker     return result;
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker 
toString() const94*ec779b8eSAndroid Build Coastguard Worker std::string PowerStats::StateResidency::toString() const {
95*ec779b8eSAndroid Build Coastguard Worker     return std::string(entity_name).append(state_name)
96*ec779b8eSAndroid Build Coastguard Worker             .append(" ").append(std::to_string(time_ms))
97*ec779b8eSAndroid Build Coastguard Worker             .append(" ").append(std::to_string(entry_count));
98*ec779b8eSAndroid Build Coastguard Worker }
99*ec779b8eSAndroid Build Coastguard Worker 
operator +=(const StateResidency & other)100*ec779b8eSAndroid Build Coastguard Worker PowerStats::StateResidency PowerStats::StateResidency::operator+=(const StateResidency& other) {
101*ec779b8eSAndroid Build Coastguard Worker     if (entity_name.empty()) entity_name = other.entity_name;
102*ec779b8eSAndroid Build Coastguard Worker     if (state_name.empty()) state_name = other.state_name;
103*ec779b8eSAndroid Build Coastguard Worker     time_ms += other.time_ms;
104*ec779b8eSAndroid Build Coastguard Worker     entry_count += other.entry_count;
105*ec779b8eSAndroid Build Coastguard Worker     return *this;
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker 
operator -=(const StateResidency & other)108*ec779b8eSAndroid Build Coastguard Worker PowerStats::StateResidency PowerStats::StateResidency::operator-=(const StateResidency& other) {
109*ec779b8eSAndroid Build Coastguard Worker     if (entity_name.empty()) entity_name = other.entity_name;
110*ec779b8eSAndroid Build Coastguard Worker     if (state_name.empty()) state_name = other.state_name;
111*ec779b8eSAndroid Build Coastguard Worker     time_ms -= other.time_ms;
112*ec779b8eSAndroid Build Coastguard Worker     entry_count -= other.entry_count;
113*ec779b8eSAndroid Build Coastguard Worker     return *this;
114*ec779b8eSAndroid Build Coastguard Worker }
115*ec779b8eSAndroid Build Coastguard Worker 
operator +(const StateResidency & other) const116*ec779b8eSAndroid Build Coastguard Worker PowerStats::StateResidency PowerStats::StateResidency::operator+(
117*ec779b8eSAndroid Build Coastguard Worker         const StateResidency& other) const {
118*ec779b8eSAndroid Build Coastguard Worker     StateResidency result = *this;
119*ec779b8eSAndroid Build Coastguard Worker     result += other;
120*ec779b8eSAndroid Build Coastguard Worker     return result;
121*ec779b8eSAndroid Build Coastguard Worker }
122*ec779b8eSAndroid Build Coastguard Worker 
operator -(const StateResidency & other) const123*ec779b8eSAndroid Build Coastguard Worker PowerStats::StateResidency PowerStats::StateResidency::operator-(
124*ec779b8eSAndroid Build Coastguard Worker         const StateResidency& other) const {
125*ec779b8eSAndroid Build Coastguard Worker     StateResidency result = *this;
126*ec779b8eSAndroid Build Coastguard Worker     result -= other;
127*ec779b8eSAndroid Build Coastguard Worker     return result;
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker 
toString() const130*ec779b8eSAndroid Build Coastguard Worker std::string PowerStats::RailEnergy::toString() const {
131*ec779b8eSAndroid Build Coastguard Worker     return std::string(subsystem_name)
132*ec779b8eSAndroid Build Coastguard Worker             .append(rail_name)
133*ec779b8eSAndroid Build Coastguard Worker             .append(" ")
134*ec779b8eSAndroid Build Coastguard Worker             .append(std::to_string(energy_uws));
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker 
operator +=(const RailEnergy & other)137*ec779b8eSAndroid Build Coastguard Worker PowerStats::RailEnergy PowerStats::RailEnergy::operator+=(const RailEnergy& other) {
138*ec779b8eSAndroid Build Coastguard Worker     if (subsystem_name.empty()) subsystem_name = other.subsystem_name;
139*ec779b8eSAndroid Build Coastguard Worker     if (rail_name.empty()) rail_name = other.rail_name;
140*ec779b8eSAndroid Build Coastguard Worker     energy_uws += other.energy_uws;
141*ec779b8eSAndroid Build Coastguard Worker     return *this;
142*ec779b8eSAndroid Build Coastguard Worker }
143*ec779b8eSAndroid Build Coastguard Worker 
operator -=(const RailEnergy & other)144*ec779b8eSAndroid Build Coastguard Worker PowerStats::RailEnergy PowerStats::RailEnergy::operator-=(const RailEnergy& other) {
145*ec779b8eSAndroid Build Coastguard Worker     if (subsystem_name.empty()) subsystem_name = other.subsystem_name;
146*ec779b8eSAndroid Build Coastguard Worker     if (rail_name.empty()) rail_name = other.rail_name;
147*ec779b8eSAndroid Build Coastguard Worker     energy_uws -= other.energy_uws;
148*ec779b8eSAndroid Build Coastguard Worker     return *this;
149*ec779b8eSAndroid Build Coastguard Worker }
150*ec779b8eSAndroid Build Coastguard Worker 
operator +(const RailEnergy & other) const151*ec779b8eSAndroid Build Coastguard Worker PowerStats::RailEnergy PowerStats::RailEnergy::operator+(const RailEnergy& other) const {
152*ec779b8eSAndroid Build Coastguard Worker     RailEnergy result = *this;
153*ec779b8eSAndroid Build Coastguard Worker     result += other;
154*ec779b8eSAndroid Build Coastguard Worker     return result;
155*ec779b8eSAndroid Build Coastguard Worker }
156*ec779b8eSAndroid Build Coastguard Worker 
operator -(const RailEnergy & other) const157*ec779b8eSAndroid Build Coastguard Worker PowerStats::RailEnergy PowerStats::RailEnergy::operator-(const RailEnergy& other) const {
158*ec779b8eSAndroid Build Coastguard Worker     RailEnergy result = *this;
159*ec779b8eSAndroid Build Coastguard Worker     result -= other;
160*ec779b8eSAndroid Build Coastguard Worker     return result;
161*ec779b8eSAndroid Build Coastguard Worker }
162*ec779b8eSAndroid Build Coastguard Worker 
toString(const std::string & prefix) const163*ec779b8eSAndroid Build Coastguard Worker std::string PowerStats::toString(const std::string& prefix) const {
164*ec779b8eSAndroid Build Coastguard Worker     std::string result;
165*ec779b8eSAndroid Build Coastguard Worker     result.append(prefix).append(metadata.toString()).append("\n");
166*ec779b8eSAndroid Build Coastguard Worker     result.append(prefix).append(health_stats.toString()).append("\n");
167*ec779b8eSAndroid Build Coastguard Worker     for (const auto &residency: power_entity_state_residency) {
168*ec779b8eSAndroid Build Coastguard Worker         result.append(prefix).append(residency.toString()).append("\n");
169*ec779b8eSAndroid Build Coastguard Worker     }
170*ec779b8eSAndroid Build Coastguard Worker     for (const auto &energy: rail_energy) {
171*ec779b8eSAndroid Build Coastguard Worker         result.append(prefix).append(energy.toString()).append("\n");
172*ec779b8eSAndroid Build Coastguard Worker     }
173*ec779b8eSAndroid Build Coastguard Worker     return result;
174*ec779b8eSAndroid Build Coastguard Worker }
175*ec779b8eSAndroid Build Coastguard Worker 
normalizedEnergy(const std::string & prefix) const176*ec779b8eSAndroid Build Coastguard Worker std::string PowerStats::normalizedEnergy(const std::string& prefix) const {
177*ec779b8eSAndroid Build Coastguard Worker     if (metadata.duration_ms == 0) return {};
178*ec779b8eSAndroid Build Coastguard Worker 
179*ec779b8eSAndroid Build Coastguard Worker     std::string result(prefix);
180*ec779b8eSAndroid Build Coastguard Worker     result.append(audio_utils_time_string_from_ns(
181*ec779b8eSAndroid Build Coastguard Worker             metadata.start_time_epoch_ms * 1'000'000).time);
182*ec779b8eSAndroid Build Coastguard Worker     result.append(" duration_boottime: ")
183*ec779b8eSAndroid Build Coastguard Worker             .append(std::to_string(metadata.duration_ms * 1e-3f))
184*ec779b8eSAndroid Build Coastguard Worker             .append(" duration_monotonic: ")
185*ec779b8eSAndroid Build Coastguard Worker             .append(std::to_string(metadata.duration_monotonic_ms * 1e-3f))
186*ec779b8eSAndroid Build Coastguard Worker             .append("\n");
187*ec779b8eSAndroid Build Coastguard Worker     if (health_stats.isValid()) {
188*ec779b8eSAndroid Build Coastguard Worker         result.append(prefix)
189*ec779b8eSAndroid Build Coastguard Worker                 .append(health_stats.normalizedEnergy(metadata.duration_ms * 1e-3f)).append("\n");
190*ec779b8eSAndroid Build Coastguard Worker     }
191*ec779b8eSAndroid Build Coastguard Worker 
192*ec779b8eSAndroid Build Coastguard Worker     // energy_uws is converted to ave W using recip time in us.
193*ec779b8eSAndroid Build Coastguard Worker     const float recipTime = 1e-3 / metadata.duration_ms;
194*ec779b8eSAndroid Build Coastguard Worker     int64_t total_energy = 0;
195*ec779b8eSAndroid Build Coastguard Worker     for (const auto& energy: rail_energy) {
196*ec779b8eSAndroid Build Coastguard Worker         total_energy += energy.energy_uws;
197*ec779b8eSAndroid Build Coastguard Worker         result.append(prefix).append(energy.subsystem_name)
198*ec779b8eSAndroid Build Coastguard Worker                 .append(energy.rail_name)
199*ec779b8eSAndroid Build Coastguard Worker                 .append(" ")
200*ec779b8eSAndroid Build Coastguard Worker                 .append(std::to_string(energy.energy_uws * 1e-6))
201*ec779b8eSAndroid Build Coastguard Worker                 .append(" ")
202*ec779b8eSAndroid Build Coastguard Worker                 .append(std::to_string(energy.energy_uws * recipTime))
203*ec779b8eSAndroid Build Coastguard Worker                 .append("\n");
204*ec779b8eSAndroid Build Coastguard Worker     }
205*ec779b8eSAndroid Build Coastguard Worker     if (total_energy != 0) {
206*ec779b8eSAndroid Build Coastguard Worker         result.append(prefix).append("total J and ave W: ")
207*ec779b8eSAndroid Build Coastguard Worker                 .append(std::to_string(total_energy * 1e-6))
208*ec779b8eSAndroid Build Coastguard Worker                 .append(" ")
209*ec779b8eSAndroid Build Coastguard Worker                 .append(std::to_string(total_energy * recipTime))
210*ec779b8eSAndroid Build Coastguard Worker                 .append("\n");
211*ec779b8eSAndroid Build Coastguard Worker     }
212*ec779b8eSAndroid Build Coastguard Worker     return result;
213*ec779b8eSAndroid Build Coastguard Worker }
214*ec779b8eSAndroid Build Coastguard Worker 
215*ec779b8eSAndroid Build Coastguard Worker // seconds, joules, watts
energyFrom(const std::string & railMatcher) const216*ec779b8eSAndroid Build Coastguard Worker std::tuple<float, float, float> PowerStats::energyFrom(const std::string& railMatcher) const {
217*ec779b8eSAndroid Build Coastguard Worker     if (metadata.duration_ms == 0) return {};
218*ec779b8eSAndroid Build Coastguard Worker 
219*ec779b8eSAndroid Build Coastguard Worker     // energy_uws is converted to ave W using recip time in us.
220*ec779b8eSAndroid Build Coastguard Worker     const float recipTime = 1e-3 / metadata.duration_ms;
221*ec779b8eSAndroid Build Coastguard Worker     int64_t total_energy = 0;
222*ec779b8eSAndroid Build Coastguard Worker     for (const auto& energy: rail_energy) {
223*ec779b8eSAndroid Build Coastguard Worker         if (energy.subsystem_name.find(railMatcher) != std::string::npos
224*ec779b8eSAndroid Build Coastguard Worker                 || energy.rail_name.find(railMatcher) != std::string::npos) {
225*ec779b8eSAndroid Build Coastguard Worker             total_energy += energy.energy_uws;
226*ec779b8eSAndroid Build Coastguard Worker         }
227*ec779b8eSAndroid Build Coastguard Worker     }
228*ec779b8eSAndroid Build Coastguard Worker     return {metadata.duration_ms * 1e-3, total_energy * 1e-6, total_energy * recipTime};
229*ec779b8eSAndroid Build Coastguard Worker }
230*ec779b8eSAndroid Build Coastguard Worker 
operator +=(const PowerStats & other)231*ec779b8eSAndroid Build Coastguard Worker PowerStats PowerStats::operator+=(const PowerStats& other) {
232*ec779b8eSAndroid Build Coastguard Worker     metadata += other.metadata;
233*ec779b8eSAndroid Build Coastguard Worker     health_stats += other.health_stats;
234*ec779b8eSAndroid Build Coastguard Worker     if (power_entity_state_residency.empty()) {
235*ec779b8eSAndroid Build Coastguard Worker         power_entity_state_residency = other.power_entity_state_residency;
236*ec779b8eSAndroid Build Coastguard Worker     } else if (power_entity_state_residency.size() == other.power_entity_state_residency.size()) {
237*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < power_entity_state_residency.size(); ++i) {
238*ec779b8eSAndroid Build Coastguard Worker             power_entity_state_residency[i] += other.power_entity_state_residency[i];
239*ec779b8eSAndroid Build Coastguard Worker         }
240*ec779b8eSAndroid Build Coastguard Worker     }
241*ec779b8eSAndroid Build Coastguard Worker     if (rail_energy.empty()) {
242*ec779b8eSAndroid Build Coastguard Worker         rail_energy = other.rail_energy;
243*ec779b8eSAndroid Build Coastguard Worker     } else if (rail_energy.size() == other.rail_energy.size()) {
244*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < rail_energy.size(); ++i) {
245*ec779b8eSAndroid Build Coastguard Worker             rail_energy[i] += other.rail_energy[i];
246*ec779b8eSAndroid Build Coastguard Worker         }
247*ec779b8eSAndroid Build Coastguard Worker     }
248*ec779b8eSAndroid Build Coastguard Worker     return *this;
249*ec779b8eSAndroid Build Coastguard Worker }
250*ec779b8eSAndroid Build Coastguard Worker 
operator -=(const PowerStats & other)251*ec779b8eSAndroid Build Coastguard Worker PowerStats PowerStats::operator-=(const PowerStats& other) {
252*ec779b8eSAndroid Build Coastguard Worker     metadata -= other.metadata;
253*ec779b8eSAndroid Build Coastguard Worker     health_stats -= other.health_stats;
254*ec779b8eSAndroid Build Coastguard Worker     if (power_entity_state_residency.empty()) {
255*ec779b8eSAndroid Build Coastguard Worker         power_entity_state_residency = other.power_entity_state_residency;
256*ec779b8eSAndroid Build Coastguard Worker     } else if (power_entity_state_residency.size() == other.power_entity_state_residency.size()) {
257*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < power_entity_state_residency.size(); ++i) {
258*ec779b8eSAndroid Build Coastguard Worker             power_entity_state_residency[i] -= other.power_entity_state_residency[i];
259*ec779b8eSAndroid Build Coastguard Worker         }
260*ec779b8eSAndroid Build Coastguard Worker     }
261*ec779b8eSAndroid Build Coastguard Worker     if (rail_energy.empty()) {
262*ec779b8eSAndroid Build Coastguard Worker         rail_energy = other.rail_energy;
263*ec779b8eSAndroid Build Coastguard Worker     } else if (rail_energy.size() == other.rail_energy.size()) {
264*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < rail_energy.size(); ++i) {
265*ec779b8eSAndroid Build Coastguard Worker             rail_energy[i] -= other.rail_energy[i];
266*ec779b8eSAndroid Build Coastguard Worker         }
267*ec779b8eSAndroid Build Coastguard Worker     }
268*ec779b8eSAndroid Build Coastguard Worker     return *this;
269*ec779b8eSAndroid Build Coastguard Worker }
270*ec779b8eSAndroid Build Coastguard Worker 
operator +(const PowerStats & other) const271*ec779b8eSAndroid Build Coastguard Worker PowerStats PowerStats::operator+(const PowerStats& other) const {
272*ec779b8eSAndroid Build Coastguard Worker     PowerStats result = *this;
273*ec779b8eSAndroid Build Coastguard Worker     result += other;
274*ec779b8eSAndroid Build Coastguard Worker     return result;
275*ec779b8eSAndroid Build Coastguard Worker }
276*ec779b8eSAndroid Build Coastguard Worker 
operator -(const PowerStats & other) const277*ec779b8eSAndroid Build Coastguard Worker PowerStats PowerStats::operator-(const PowerStats& other) const {
278*ec779b8eSAndroid Build Coastguard Worker     PowerStats result = *this;
279*ec779b8eSAndroid Build Coastguard Worker     result -= other;
280*ec779b8eSAndroid Build Coastguard Worker     return result;
281*ec779b8eSAndroid Build Coastguard Worker }
282*ec779b8eSAndroid Build Coastguard Worker 
283*ec779b8eSAndroid Build Coastguard Worker } // namespace android::media::psh_utils
284