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