1 /*
2  * Copyright (C) 2023 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 
17 package com.android.server.power.stats;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.os.BatteryConsumer;
22 import android.os.PersistableBundle;
23 import android.util.SparseArray;
24 import android.util.Xml;
25 
26 import androidx.test.filters.SmallTest;
27 import androidx.test.runner.AndroidJUnit4;
28 
29 import com.android.internal.os.PowerStats;
30 import com.android.modules.utils.TypedXmlPullParser;
31 import com.android.modules.utils.TypedXmlSerializer;
32 
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 
37 import java.io.ByteArrayInputStream;
38 import java.io.ByteArrayOutputStream;
39 import java.text.ParseException;
40 
41 @RunWith(AndroidJUnit4.class)
42 @SmallTest
43 public class AggregatedPowerStatsTest {
44     private static final int TEST_POWER_COMPONENT = 1077;
45     private static final int APP_1 = 27;
46     private static final int APP_2 = 42;
47     private static final int COMPONENT_STATE_0 = 0;
48     private static final int COMPONENT_STATE_1 = 1;
49     private static final int COMPONENT_STATE_2 = 2;
50 
51     private AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
52     private PowerStats.Descriptor mPowerComponentDescriptor;
53 
54     @Before
setup()55     public void setup() throws ParseException {
56         mAggregatedPowerStatsConfig = new AggregatedPowerStatsConfig();
57         mAggregatedPowerStatsConfig.trackPowerComponent(TEST_POWER_COMPONENT)
58                 .trackDeviceStates(
59                         AggregatedPowerStatsConfig.STATE_POWER,
60                         AggregatedPowerStatsConfig.STATE_SCREEN)
61                 .trackUidStates(
62                         AggregatedPowerStatsConfig.STATE_POWER,
63                         AggregatedPowerStatsConfig.STATE_SCREEN,
64                         AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
65 
66         SparseArray<String> stateLabels = new SparseArray<>();
67         stateLabels.put(COMPONENT_STATE_1, "one");
68         mPowerComponentDescriptor = new PowerStats.Descriptor(TEST_POWER_COMPONENT, "fan", 2,
69                 stateLabels, 1, 3, PersistableBundle.forPair("speed", "fast"));
70     }
71 
72     @Test
aggregation()73     public void aggregation() {
74         AggregatedPowerStats stats = prepareAggregatePowerStats();
75 
76         verifyAggregatedPowerStats(stats);
77     }
78 
79     @Test
xmlPersistence()80     public void xmlPersistence() throws Exception {
81         AggregatedPowerStats stats = prepareAggregatePowerStats();
82 
83         ByteArrayOutputStream baos = new ByteArrayOutputStream();
84         TypedXmlSerializer serializer = Xml.newFastSerializer();
85         serializer.setOutput(baos, "UTF-8");
86         stats.writeXml(serializer);
87         serializer.flush();
88 
89         TypedXmlPullParser parser = Xml.newFastPullParser();
90         parser.setInput(new ByteArrayInputStream(baos.toByteArray()), "UTF-8");
91         AggregatedPowerStats actualStats = AggregatedPowerStats.createFromXml(parser,
92                 mAggregatedPowerStatsConfig);
93 
94         verifyAggregatedPowerStats(actualStats);
95     }
96 
prepareAggregatePowerStats()97     private AggregatedPowerStats prepareAggregatePowerStats() {
98         AggregatedPowerStats stats = new AggregatedPowerStats(mAggregatedPowerStatsConfig);
99 
100         PowerStats ps = new PowerStats(mPowerComponentDescriptor);
101         stats.addPowerStats(ps, 0);
102 
103         stats.addClockUpdate(1000, 456);
104         stats.setDuration(789);
105 
106         stats.setDeviceState(AggregatedPowerStatsConfig.STATE_SCREEN,
107                 AggregatedPowerStatsConfig.SCREEN_STATE_ON, 2000);
108         stats.setUidState(APP_1, AggregatedPowerStatsConfig.STATE_PROCESS_STATE,
109                 BatteryConsumer.PROCESS_STATE_CACHED, 2000);
110         stats.setUidState(APP_2, AggregatedPowerStatsConfig.STATE_PROCESS_STATE,
111                 BatteryConsumer.PROCESS_STATE_FOREGROUND, 2000);
112 
113         ps.stats[0] = 100;
114         ps.stats[1] = 987;
115 
116         ps.stateStats.put(COMPONENT_STATE_0, new long[]{1111});
117         ps.stateStats.put(COMPONENT_STATE_1, new long[]{5000});
118 
119         ps.uidStats.put(APP_1, new long[]{389, 0, 739});
120         ps.uidStats.put(APP_2, new long[]{278, 314, 628});
121 
122         stats.addPowerStats(ps, 3000);
123 
124         stats.setDeviceState(AggregatedPowerStatsConfig.STATE_SCREEN,
125                 AggregatedPowerStatsConfig.SCREEN_STATE_OTHER, 4000);
126         stats.setUidState(APP_2, AggregatedPowerStatsConfig.STATE_PROCESS_STATE,
127                 BatteryConsumer.PROCESS_STATE_BACKGROUND, 4000);
128 
129         ps.stats[0] = 444;
130         ps.stats[1] = 0;
131 
132         ps.stateStats.clear();
133         ps.stateStats.put(COMPONENT_STATE_1, new long[]{1000});
134         ps.stateStats.put(COMPONENT_STATE_2, new long[]{9000});
135 
136         ps.uidStats.put(APP_1, new long[]{0, 0, 400});
137         ps.uidStats.put(APP_2, new long[]{100, 200, 300});
138 
139         stats.addPowerStats(ps, 5000);
140         return stats;
141     }
142 
verifyAggregatedPowerStats(AggregatedPowerStats stats)143     private void verifyAggregatedPowerStats(AggregatedPowerStats stats) {
144         PowerStats.Descriptor descriptor = stats.getPowerComponentStats(TEST_POWER_COMPONENT)
145                 .getPowerStatsDescriptor();
146         assertThat(descriptor.powerComponentId).isEqualTo(TEST_POWER_COMPONENT);
147         assertThat(descriptor.name).isEqualTo("fan");
148         assertThat(descriptor.statsArrayLength).isEqualTo(2);
149         assertThat(descriptor.uidStatsArrayLength).isEqualTo(3);
150         assertThat(descriptor.extras.getString("speed")).isEqualTo("fast");
151 
152         assertThat(getDeviceStats(stats,
153                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
154                 AggregatedPowerStatsConfig.SCREEN_STATE_ON))
155                 .isEqualTo(new long[]{322, 987});
156 
157         assertThat(getDeviceStats(stats,
158                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
159                 AggregatedPowerStatsConfig.SCREEN_STATE_OTHER))
160                 .isEqualTo(new long[]{222, 0});
161 
162         assertThat(getStateStats(stats, COMPONENT_STATE_0,
163                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
164                 AggregatedPowerStatsConfig.SCREEN_STATE_ON))
165                 .isEqualTo(new long[]{1111});
166 
167         assertThat(getStateStats(stats, COMPONENT_STATE_1,
168                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
169                 AggregatedPowerStatsConfig.SCREEN_STATE_ON))
170                 .isEqualTo(new long[]{5500});
171 
172         assertThat(getStateStats(stats, COMPONENT_STATE_1,
173                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
174                 AggregatedPowerStatsConfig.SCREEN_STATE_OTHER))
175                 .isEqualTo(new long[]{500});
176 
177         assertThat(getStateStats(stats, COMPONENT_STATE_2,
178                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
179                 AggregatedPowerStatsConfig.SCREEN_STATE_ON))
180                 .isEqualTo(new long[]{4500});
181 
182         assertThat(getStateStats(stats, COMPONENT_STATE_2,
183                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
184                 AggregatedPowerStatsConfig.SCREEN_STATE_OTHER))
185                 .isEqualTo(new long[]{4500});
186 
187         assertThat(getUidDeviceStats(stats,
188                 APP_1,
189                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
190                 AggregatedPowerStatsConfig.SCREEN_STATE_ON,
191                 BatteryConsumer.PROCESS_STATE_UNSPECIFIED))
192                 .isEqualTo(new long[]{259, 0, 492});
193 
194         assertThat(getUidDeviceStats(stats,
195                 APP_1,
196                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
197                 AggregatedPowerStatsConfig.SCREEN_STATE_ON,
198                 BatteryConsumer.PROCESS_STATE_CACHED))
199                 .isEqualTo(new long[]{129, 0, 446});
200 
201         assertThat(getUidDeviceStats(stats,
202                 APP_1,
203                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
204                 AggregatedPowerStatsConfig.SCREEN_STATE_OTHER,
205                 BatteryConsumer.PROCESS_STATE_CACHED))
206                 .isEqualTo(new long[]{0, 0, 200});
207 
208         assertThat(getUidDeviceStats(stats,
209                 APP_2,
210                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
211                 AggregatedPowerStatsConfig.SCREEN_STATE_ON,
212                 BatteryConsumer.PROCESS_STATE_UNSPECIFIED))
213                 .isEqualTo(new long[]{185, 209, 418});
214 
215         assertThat(getUidDeviceStats(stats,
216                 APP_2,
217                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
218                 AggregatedPowerStatsConfig.SCREEN_STATE_ON,
219                 BatteryConsumer.PROCESS_STATE_FOREGROUND))
220                 .isEqualTo(new long[]{142, 204, 359});
221 
222         assertThat(getUidDeviceStats(stats,
223                 APP_2,
224                 AggregatedPowerStatsConfig.POWER_STATE_BATTERY,
225                 AggregatedPowerStatsConfig.SCREEN_STATE_OTHER,
226                 BatteryConsumer.PROCESS_STATE_BACKGROUND))
227                 .isEqualTo(new long[]{50, 100, 150});
228     }
229 
getDeviceStats(AggregatedPowerStats stats, int... states)230     private static long[] getDeviceStats(AggregatedPowerStats stats, int... states) {
231         PowerComponentAggregatedPowerStats powerComponentStats =
232                 stats.getPowerComponentStats(TEST_POWER_COMPONENT);
233         long[] out = new long[powerComponentStats.getPowerStatsDescriptor().statsArrayLength];
234         powerComponentStats.getDeviceStats(out, states);
235         return out;
236     }
237 
getStateStats(AggregatedPowerStats stats, int key, int... states)238     private static long[] getStateStats(AggregatedPowerStats stats, int key, int... states) {
239         PowerComponentAggregatedPowerStats powerComponentStats =
240                 stats.getPowerComponentStats(TEST_POWER_COMPONENT);
241         long[] out = new long[powerComponentStats.getPowerStatsDescriptor().stateStatsArrayLength];
242         powerComponentStats.getStateStats(out, key, states);
243         return out;
244     }
245 
getUidDeviceStats(AggregatedPowerStats stats, int uid, int... states)246     private static long[] getUidDeviceStats(AggregatedPowerStats stats, int uid, int... states) {
247         PowerComponentAggregatedPowerStats powerComponentStats =
248                 stats.getPowerComponentStats(TEST_POWER_COMPONENT);
249         long[] out = new long[powerComponentStats.getPowerStatsDescriptor().uidStatsArrayLength];
250         powerComponentStats.getUidStats(out, uid, states);
251         return out;
252     }
253 }
254