1 /* 2 * Copyright (C) 2018 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 package android.cts.statsd.validation; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static com.google.common.truth.Truth.assertWithMessage; 20 21 import android.cts.statsd.metric.MetricsUtils; 22 import android.cts.statsdatom.lib.AtomTestUtils; 23 import android.cts.statsdatom.lib.ConfigUtils; 24 import android.cts.statsdatom.lib.DeviceUtils; 25 import android.cts.statsdatom.lib.ReportUtils; 26 import android.os.BatteryPluggedStateEnum; 27 import android.os.BatteryStatsProto; 28 import android.os.UidProto; 29 import android.os.UidProto.Wakelock; 30 import android.os.WakeLockLevelEnum; 31 import android.platform.test.annotations.RestrictedBuildTest; 32 import android.view.DisplayStateEnum; 33 34 import com.android.internal.os.StatsdConfigProto.AtomMatcher; 35 import com.android.internal.os.StatsdConfigProto.DurationMetric; 36 import com.android.internal.os.StatsdConfigProto.FieldMatcher; 37 import com.android.internal.os.StatsdConfigProto.FieldValueMatcher; 38 import com.android.internal.os.StatsdConfigProto.LogicalOperation; 39 import com.android.internal.os.StatsdConfigProto.Position; 40 import com.android.internal.os.StatsdConfigProto.Predicate; 41 import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher; 42 import com.android.internal.os.StatsdConfigProto.SimplePredicate; 43 import com.android.internal.os.StatsdConfigProto.StatsdConfig; 44 import com.android.internal.os.StatsdConfigProto.TimeUnit; 45 import com.android.os.AtomsProto.Atom; 46 import com.android.os.AtomsProto.PluggedStateChanged; 47 import com.android.os.AtomsProto.ScreenStateChanged; 48 import com.android.os.AtomsProto.WakelockStateChanged; 49 import com.android.os.StatsLog.DimensionsValue; 50 import com.android.os.StatsLog.DurationBucketInfo; 51 import com.android.os.StatsLog.DurationMetricData; 52 import com.android.os.StatsLog.EventMetricData; 53 import com.android.os.StatsLog.StatsLogReport; 54 import com.android.tradefed.build.IBuildInfo; 55 import com.android.tradefed.log.LogUtil.CLog; 56 import com.android.tradefed.testtype.DeviceTestCase; 57 import com.android.tradefed.testtype.IBuildReceiver; 58 import com.android.tradefed.util.RunUtil; 59 60 import com.google.common.collect.Range; 61 import com.google.protobuf.ExtensionRegistry; 62 63 import java.util.Arrays; 64 import java.util.HashMap; 65 import java.util.HashSet; 66 import java.util.List; 67 import java.util.Set; 68 69 /** 70 * Side-by-side comparison between statsd and batterystats. 71 */ 72 public class ValidationTests extends DeviceTestCase implements IBuildReceiver { 73 74 private IBuildInfo mCtsBuild; 75 76 @Override setUp()77 protected void setUp() throws Exception { 78 super.setUp(); 79 assertThat(mCtsBuild).isNotNull(); 80 ConfigUtils.removeConfig(getDevice()); 81 ReportUtils.clearReports(getDevice()); 82 DeviceUtils.installTestApp(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_APK, 83 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE, mCtsBuild); 84 RunUtil.getDefault().sleep(1000); 85 DeviceUtils.turnBatteryStatsAutoResetOff( 86 getDevice()); // Turn off Battery Stats auto resetting 87 } 88 89 @Override tearDown()90 protected void tearDown() throws Exception { 91 ConfigUtils.removeConfig(getDevice()); 92 ReportUtils.clearReports(getDevice()); 93 DeviceUtils.uninstallTestApp(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 94 DeviceUtils.resetBatteryStatus(getDevice()); 95 DeviceUtils.turnScreenOn(getDevice()); 96 DeviceUtils.turnBatteryStatsAutoResetOn(getDevice()); 97 super.tearDown(); 98 } 99 100 @Override setBuild(IBuildInfo buildInfo)101 public void setBuild(IBuildInfo buildInfo) { 102 mCtsBuild = buildInfo; 103 } 104 105 private static final String TAG = "Statsd.ValidationTests"; 106 private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive"; 107 private static final boolean ENABLE_LOAD_TEST = false; 108 testPartialWakelock()109 public void testPartialWakelock() throws Exception { 110 if (!DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)) return; 111 resetBatteryStats(); 112 DeviceUtils.unplugDevice(getDevice()); 113 DeviceUtils.flushBatteryStatsHandlers(getDevice()); 114 // AoD needs to be turned off because the screen should go into an off state. But, if AoD is 115 // on and the device doesn't support STATE_DOZE, the screen sadly goes back to STATE_ON. 116 String aodState = DeviceUtils.getAodState(getDevice()); 117 DeviceUtils.setAodState(getDevice(), "0"); 118 DeviceUtils.turnScreenOff(getDevice()); 119 120 final int atomTag = Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER; 121 Set<Integer> wakelockOn = new HashSet<>(Arrays.asList( 122 WakelockStateChanged.State.ACQUIRE_VALUE, 123 WakelockStateChanged.State.CHANGE_ACQUIRE_VALUE)); 124 Set<Integer> wakelockOff = new HashSet<>(Arrays.asList( 125 WakelockStateChanged.State.RELEASE_VALUE, 126 WakelockStateChanged.State.CHANGE_RELEASE_VALUE)); 127 128 final String EXPECTED_TAG = "StatsdPartialWakelock"; 129 final WakeLockLevelEnum EXPECTED_LEVEL = WakeLockLevelEnum.PARTIAL_WAKE_LOCK; 130 131 // Add state sets to the list in order. 132 List<Set<Integer>> stateSet = Arrays.asList(wakelockOn, wakelockOff); 133 134 ConfigUtils.uploadConfigForPushedAtomWithUid(getDevice(), 135 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE, atomTag, true); // True: uses attribution. 136 DeviceUtils.runDeviceTests(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", 137 "testWakelockState"); 138 139 // Sorted list of events in order in which they occurred. 140 List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 141 142 //=================== verify that statsd is correct ===============// 143 // Assert that the events happened in the expected order. 144 AtomTestUtils.assertStatesOccurred(stateSet, data, 145 atom -> atom.getWakelockStateChanged().getState().getNumber()); 146 147 for (EventMetricData event : data) { 148 String tag = event.getAtom().getWakelockStateChanged().getTag(); 149 WakeLockLevelEnum type = event.getAtom().getWakelockStateChanged().getType(); 150 assertThat(tag).isEqualTo(EXPECTED_TAG); 151 assertThat(type).isEqualTo(EXPECTED_LEVEL); 152 } 153 } 154 155 @RestrictedBuildTest testPartialWakelockDuration()156 public void testPartialWakelockDuration() throws Exception { 157 if (!DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)) return; 158 159 // getUid() needs shell command via ADB. turnScreenOff() sometimes let system go to suspend. 160 // ADB disconnection causes failure of getUid(). Move up here before turnScreenOff(). 161 final int EXPECTED_UID = DeviceUtils.getAppUid(getDevice(), 162 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 163 164 DeviceUtils.turnScreenOn(getDevice()); // To ensure that the ScreenOff later gets logged. 165 // AoD needs to be turned off because the screen should go into an off state. But, if AoD is 166 // on and the device doesn't support STATE_DOZE, the screen sadly goes back to STATE_ON. 167 String aodState = DeviceUtils.getAodState(getDevice()); 168 DeviceUtils.setAodState(getDevice(), "0"); 169 uploadWakelockDurationBatteryStatsConfig(TimeUnit.CTS); 170 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_SHORT); 171 resetBatteryStats(); 172 DeviceUtils.unplugDevice(getDevice()); 173 DeviceUtils.turnScreenOff(getDevice()); 174 DeviceUtils.flushBatteryStatsHandlers(getDevice()); 175 176 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_SHORT); 177 178 DeviceUtils.runDeviceTests(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", 179 "testWakelockState"); 180 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); // Make sure the one second bucket has ended. 181 182 183 final String EXPECTED_TAG = "StatsdPartialWakelock"; 184 final long EXPECTED_TAG_HASH = Long.parseUnsignedLong("15814523794762874414"); 185 final int MIN_DURATION = 350; 186 final int MAX_DURATION = 700; 187 188 HashMap<Integer, HashMap<Long, Long>> statsdWakelockData = getStatsdWakelockData(); 189 190 // Get the statsd wakelock time and make sure it's reasonable. 191 assertWithMessage("No wakelocks with uid %s in statsd", EXPECTED_UID) 192 .that(statsdWakelockData).containsKey(EXPECTED_UID); 193 assertWithMessage("No wakelocks with tag %s in statsd", EXPECTED_TAG) 194 .that(statsdWakelockData.get(EXPECTED_UID)).containsKey(EXPECTED_TAG_HASH); 195 long statsdDurationMs = statsdWakelockData.get(EXPECTED_UID) 196 .get(EXPECTED_TAG_HASH) / 1_000_000; 197 assertWithMessage( 198 "Wakelock in statsd with uid %s and tag %s was too short or too long", 199 EXPECTED_UID, EXPECTED_TAG 200 ).that(statsdDurationMs).isIn(Range.closed((long) MIN_DURATION, (long) MAX_DURATION)); 201 202 DeviceUtils.setAodState(getDevice(), aodState); // restores AOD to initial state. 203 } 204 testPartialWakelockLoad()205 public void testPartialWakelockLoad() throws Exception { 206 if (!ENABLE_LOAD_TEST) return; 207 DeviceUtils.turnScreenOn(getDevice()); // To ensure that the ScreenOff later gets logged. 208 uploadWakelockDurationBatteryStatsConfig(TimeUnit.CTS); 209 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_SHORT); 210 resetBatteryStats(); 211 DeviceUtils.unplugDevice(getDevice()); 212 DeviceUtils.turnScreenOff(getDevice()); 213 214 DeviceUtils.runDeviceTests(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", 215 "testWakelockLoad"); 216 // Give time for stuck wakelocks to increase duration. 217 RunUtil.getDefault().sleep(10_000); 218 219 220 final String EXPECTED_TAG = "StatsdPartialWakelock"; 221 final int EXPECTED_UID = DeviceUtils.getAppUid(getDevice(), 222 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 223 final int NUM_THREADS = 16; 224 final int NUM_COUNT_PER_THREAD = 1000; 225 final int MAX_DURATION_MS = 15_000; 226 final int MIN_DURATION_MS = 1_000; 227 228 229 // BatteryStatsProto batterystatsProto = getBatteryStatsProto(); 230 // HashMap<Integer, HashMap<Long, Long>> statsdWakelockData = getStatsdWakelockData(); 231 232 // TODO: this fails because we only have the hashes of the wakelock tags in statsd. 233 // If we want to run this test, we need to fix this. 234 235 // Verify batterystats output is reasonable. 236 // boolean foundUid = false; 237 // for (UidProto uidProto : batterystatsProto.getUidsList()) { 238 // if (uidProto.getUid() == EXPECTED_UID) { 239 // foundUid = true; 240 // CLog.d("Battery stats has the following wakelocks: \n" + 241 // uidProto.getWakelocksList()); 242 // assertTrue("UidProto has size " + uidProto.getWakelocksList().size() + 243 // " wakelocks in it. Expected " + NUM_THREADS + " wakelocks.", 244 // uidProto.getWakelocksList().size() == NUM_THREADS); 245 // 246 // for (Wakelock wl : uidProto.getWakelocksList()) { 247 // String tag = wl.getName(); 248 // assertTrue("Wakelock tag in batterystats " + tag + " does not contain " 249 // + "expected tag " + EXPECTED_TAG, tag.contains(EXPECTED_TAG)); 250 // assertTrue("Wakelock in batterystats with tag " + tag + " does not have any " 251 // + "partial wakelock data.", wl.hasPartial()); 252 // assertTrue("Wakelock in batterystats with tag " + tag + " tag has count " + 253 // wl.getPartial().getCount() + " Expected " + NUM_COUNT_PER_THREAD, 254 // wl.getPartial().getCount() == NUM_COUNT_PER_THREAD); 255 // long bsDurationMs = wl.getPartial().getTotalDurationMs(); 256 // assertTrue("Wakelock in batterystats with uid " + EXPECTED_UID + " and tag " 257 // + EXPECTED_TAG + "was too short. Expected " + MIN_DURATION_MS + 258 // ", received " + bsDurationMs, bsDurationMs >= MIN_DURATION_MS); 259 // assertTrue("Wakelock in batterystats with uid " + EXPECTED_UID + " and tag " 260 // + EXPECTED_TAG + "was too long. Expected " + MAX_DURATION_MS + 261 // ", received " + bsDurationMs, bsDurationMs <= MAX_DURATION_MS); 262 // 263 // // Validate statsd. 264 // long statsdDurationNs = statsdWakelockData.get(EXPECTED_UID).get(tag); 265 // long statsdDurationMs = statsdDurationNs / 1_000_000; 266 // long difference = Math.abs(statsdDurationMs - bsDurationMs); 267 // assertTrue("Unusually large difference in wakelock duration for tag: " + 268 // tag + 269 // ". Statsd had duration " + statsdDurationMs + 270 // " and batterystats had duration " + bsDurationMs, 271 // difference <= bsDurationMs / 10); 272 // 273 // } 274 // } 275 // } 276 // assertTrue("Did not find uid " + EXPECTED_UID + " in batterystats.", foundUid); 277 // 278 // // Assert that the wakelock appears in statsd and is correct. 279 // assertTrue("Could not find any wakelocks with uid " + EXPECTED_UID + " in statsd", 280 // statsdWakelockData.containsKey(EXPECTED_UID)); 281 // HashMap<String, Long> expectedWakelocks = statsdWakelockData.get(EXPECTED_UID); 282 // assertEquals("Expected " + NUM_THREADS + " wakelocks in statsd with UID " + 283 // EXPECTED_UID + 284 // ". Received " + expectedWakelocks.size(), expectedWakelocks.size(), NUM_THREADS); 285 } 286 287 // Helper functions 288 // TODO: Refactor these into some utils class. 289 getStatsdWakelockData()290 public HashMap<Integer, HashMap<Long, Long>> getStatsdWakelockData() throws Exception { 291 StatsLogReport report = ReportUtils.getStatsLogReport(getDevice(), 292 ExtensionRegistry.getEmptyRegistry()); 293 CLog.d("Received the following stats log report: \n" + report.toString()); 294 295 // Stores total duration of each wakelock across buckets. 296 HashMap<Integer, HashMap<Long, Long>> statsdWakelockData = new HashMap<>(); 297 298 for (DurationMetricData data : report.getDurationMetrics().getDataList()) { 299 // Gets tag and uid. 300 List<DimensionsValue> dims = data.getDimensionLeafValuesInWhatList(); 301 assertThat(dims).hasSize(2); 302 boolean hasTag = false; 303 long tag = 0; 304 int uid = -1; 305 long duration = 0; 306 for (DimensionsValue dim : dims) { 307 if (dim.hasValueInt()) { 308 uid = dim.getValueInt(); 309 } else if (dim.hasValueStrHash()) { 310 hasTag = true; 311 tag = dim.getValueStrHash(); 312 } 313 } 314 assertWithMessage("Did not receive a tag for the wakelock").that(hasTag).isTrue(); 315 assertWithMessage("Did not receive a uid for the wakelock").that(uid).isNotEqualTo(-1); 316 317 // Gets duration. 318 for (DurationBucketInfo bucketInfo : data.getBucketInfoList()) { 319 duration += bucketInfo.getDurationNanos(); 320 } 321 322 // Store the info. 323 if (statsdWakelockData.containsKey(uid)) { 324 HashMap<Long, Long> tagToDuration = statsdWakelockData.get(uid); 325 tagToDuration.put(tag, duration); 326 } else { 327 HashMap<Long, Long> tagToDuration = new HashMap<>(); 328 tagToDuration.put(tag, duration); 329 statsdWakelockData.put(uid, tagToDuration); 330 } 331 } 332 CLog.d("follow: statsdwakelockdata is: " + statsdWakelockData); 333 return statsdWakelockData; 334 } 335 getBatteryStatsPartialWakelock(BatteryStatsProto proto, long uid, String tag)336 private android.os.TimerProto getBatteryStatsPartialWakelock(BatteryStatsProto proto, 337 long uid, String tag) { 338 if (proto.getUidsList().size() < 1) { 339 CLog.w("Batterystats proto contains no uids"); 340 return null; 341 } 342 boolean hadUid = false; 343 for (UidProto uidProto : proto.getUidsList()) { 344 if (uidProto.getUid() == uid) { 345 hadUid = true; 346 for (Wakelock wl : uidProto.getWakelocksList()) { 347 if (tag.equals(wl.getName())) { 348 if (wl.hasPartial()) { 349 return wl.getPartial(); 350 } 351 CLog.w("Batterystats had wakelock for uid (" + uid + ") " 352 + "with tag (" + tag + ") " 353 + "but it didn't have a partial wakelock"); 354 } 355 } 356 CLog.w("Batterystats didn't have a partial wakelock for uid " + uid 357 + " with tag " + tag); 358 } 359 } 360 if (!hadUid) CLog.w("Batterystats didn't have uid " + uid); 361 return null; 362 } 363 uploadWakelockDurationBatteryStatsConfig(TimeUnit bucketsize)364 public void uploadWakelockDurationBatteryStatsConfig(TimeUnit bucketsize) throws Exception { 365 final int atomTag = Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER; 366 String metricName = "DURATION_PARTIAL_WAKELOCK_PER_TAG_UID_WHILE_SCREEN_OFF_ON_BATTERY"; 367 int metricId = metricName.hashCode(); 368 369 String partialWakelockIsOnName = "PARTIAL_WAKELOCK_IS_ON"; 370 int partialWakelockIsOnId = partialWakelockIsOnName.hashCode(); 371 372 String partialWakelockOnName = "PARTIAL_WAKELOCK_ON"; 373 int partialWakelockOnId = partialWakelockOnName.hashCode(); 374 String partialWakelockOffName = "PARTIAL_WAKELOCK_OFF"; 375 int partialWakelockOffId = partialWakelockOffName.hashCode(); 376 377 String partialWakelockAcquireName = "PARTIAL_WAKELOCK_ACQUIRE"; 378 int partialWakelockAcquireId = partialWakelockAcquireName.hashCode(); 379 String partialWakelockChangeAcquireName = "PARTIAL_WAKELOCK_CHANGE_ACQUIRE"; 380 int partialWakelockChangeAcquireId = partialWakelockChangeAcquireName.hashCode(); 381 382 String partialWakelockReleaseName = "PARTIAL_WAKELOCK_RELEASE"; 383 int partialWakelockReleaseId = partialWakelockReleaseName.hashCode(); 384 String partialWakelockChangeReleaseName = "PARTIAL_WAKELOCK_CHANGE_RELEASE"; 385 int partialWakelockChangeReleaseId = partialWakelockChangeReleaseName.hashCode(); 386 387 388 String screenOffBatteryOnName = "SCREEN_IS_OFF_ON_BATTERY"; 389 int screenOffBatteryOnId = screenOffBatteryOnName.hashCode(); 390 391 String screenStateUnknownName = "SCREEN_STATE_UNKNOWN"; 392 int screenStateUnknownId = screenStateUnknownName.hashCode(); 393 String screenStateOffName = "SCREEN_STATE_OFF"; 394 int screenStateOffId = screenStateOffName.hashCode(); 395 String screenStateOnName = "SCREEN_STATE_ON"; 396 int screenStateOnId = screenStateOnName.hashCode(); 397 String screenStateDozeName = "SCREEN_STATE_DOZE"; 398 int screenStateDozeId = screenStateDozeName.hashCode(); 399 String screenStateDozeSuspendName = "SCREEN_STATE_DOZE_SUSPEND"; 400 int screenStateDozeSuspendId = screenStateDozeSuspendName.hashCode(); 401 String screenStateVrName = "SCREEN_STATE_VR"; 402 int screenStateVrId = screenStateVrName.hashCode(); 403 String screenStateOnSuspendName = "SCREEN_STATE_ON_SUSPEND"; 404 int screenStateOnSuspendId = screenStateOnSuspendName.hashCode(); 405 406 String screenTurnedOnName = "SCREEN_TURNED_ON"; 407 int screenTurnedOnId = screenTurnedOnName.hashCode(); 408 String screenTurnedOffName = "SCREEN_TURNED_OFF"; 409 int screenTurnedOffId = screenTurnedOffName.hashCode(); 410 411 String screenIsOffName = "SCREEN_IS_OFF"; 412 int screenIsOffId = screenIsOffName.hashCode(); 413 414 String pluggedStateBatteryPluggedNoneName = "PLUGGED_STATE_BATTERY_PLUGGED_NONE"; 415 int pluggedStateBatteryPluggedNoneId = pluggedStateBatteryPluggedNoneName.hashCode(); 416 String pluggedStateBatteryPluggedAcName = "PLUGGED_STATE_BATTERY_PLUGGED_AC"; 417 int pluggedStateBatteryPluggedAcId = pluggedStateBatteryPluggedAcName.hashCode(); 418 String pluggedStateBatteryPluggedUsbName = "PLUGGED_STATE_BATTERY_PLUGGED_USB"; 419 int pluggedStateBatteryPluggedUsbId = pluggedStateBatteryPluggedUsbName.hashCode(); 420 String pluggedStateBatteryPluggedWlName = "PLUGGED_STATE_BATTERY_PLUGGED_WIRELESS"; 421 int pluggedStateBatteryPluggedWirelessId = pluggedStateBatteryPluggedWlName.hashCode(); 422 423 String pluggedStateBatteryPluggedName = "PLUGGED_STATE_BATTERY_PLUGGED"; 424 int pluggedStateBatteryPluggedId = pluggedStateBatteryPluggedName.hashCode(); 425 426 String deviceIsUnpluggedName = "DEVICE_IS_UNPLUGGED"; 427 int deviceIsUnpluggedId = deviceIsUnpluggedName.hashCode(); 428 429 430 FieldMatcher.Builder dimensions = FieldMatcher.newBuilder() 431 .setField(atomTag) 432 .addChild(FieldMatcher.newBuilder() 433 .setField(WakelockStateChanged.TAG_FIELD_NUMBER)) 434 .addChild(FieldMatcher.newBuilder() 435 .setField(1) 436 .setPosition(Position.FIRST) 437 .addChild(FieldMatcher.newBuilder() 438 .setField(1))); 439 440 AtomMatcher.Builder wakelockAcquire = AtomMatcher.newBuilder() 441 .setId(partialWakelockAcquireId) 442 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 443 .setAtomId(atomTag) 444 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 445 .setField(WakelockStateChanged.TYPE_FIELD_NUMBER) 446 .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE)) 447 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 448 .setField(WakelockStateChanged.STATE_FIELD_NUMBER) 449 .setEqInt(WakelockStateChanged.State.ACQUIRE_VALUE))); 450 451 AtomMatcher.Builder wakelockChangeAcquire = AtomMatcher.newBuilder() 452 .setId(partialWakelockChangeAcquireId) 453 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 454 .setAtomId(atomTag) 455 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 456 .setField(WakelockStateChanged.TYPE_FIELD_NUMBER) 457 .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE)) 458 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 459 .setField(WakelockStateChanged.STATE_FIELD_NUMBER) 460 .setEqInt(WakelockStateChanged.State.CHANGE_ACQUIRE_VALUE))); 461 462 AtomMatcher.Builder wakelockRelease = AtomMatcher.newBuilder() 463 .setId(partialWakelockReleaseId) 464 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 465 .setAtomId(atomTag) 466 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 467 .setField(WakelockStateChanged.TYPE_FIELD_NUMBER) 468 .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE)) 469 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 470 .setField(WakelockStateChanged.STATE_FIELD_NUMBER) 471 .setEqInt(WakelockStateChanged.State.RELEASE_VALUE))); 472 473 AtomMatcher.Builder wakelockChangeRelease = AtomMatcher.newBuilder() 474 .setId(partialWakelockChangeReleaseId) 475 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 476 .setAtomId(atomTag) 477 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 478 .setField(WakelockStateChanged.TYPE_FIELD_NUMBER) 479 .setEqInt(WakeLockLevelEnum.PARTIAL_WAKE_LOCK_VALUE)) 480 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 481 .setField(WakelockStateChanged.STATE_FIELD_NUMBER) 482 .setEqInt(WakelockStateChanged.State.CHANGE_RELEASE_VALUE))); 483 484 AtomMatcher.Builder wakelockOn = AtomMatcher.newBuilder() 485 .setId(partialWakelockOnId) 486 .setCombination(AtomMatcher.Combination.newBuilder() 487 .setOperation(LogicalOperation.OR) 488 .addMatcher(partialWakelockAcquireId) 489 .addMatcher(partialWakelockChangeAcquireId)); 490 491 AtomMatcher.Builder wakelockOff = AtomMatcher.newBuilder() 492 .setId(partialWakelockOffId) 493 .setCombination(AtomMatcher.Combination.newBuilder() 494 .setOperation(LogicalOperation.OR) 495 .addMatcher(partialWakelockReleaseId) 496 .addMatcher(partialWakelockChangeReleaseId)); 497 498 499 Predicate.Builder wakelockPredicate = Predicate.newBuilder() 500 .setId(partialWakelockIsOnId) 501 .setSimplePredicate(SimplePredicate.newBuilder() 502 .setStart(partialWakelockOnId) 503 .setStop(partialWakelockOffId) 504 .setCountNesting(true) 505 .setDimensions(dimensions)); 506 507 AtomMatcher.Builder pluggedStateBatteryPluggedNone = AtomMatcher.newBuilder() 508 .setId(pluggedStateBatteryPluggedNoneId) 509 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 510 .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER) 511 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 512 .setField(PluggedStateChanged.STATE_FIELD_NUMBER) 513 .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_NONE_VALUE))); 514 515 AtomMatcher.Builder pluggedStateBatteryPluggedAc = AtomMatcher.newBuilder() 516 .setId(pluggedStateBatteryPluggedAcId) 517 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 518 .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER) 519 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 520 .setField(PluggedStateChanged.STATE_FIELD_NUMBER) 521 .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_AC_VALUE))); 522 523 AtomMatcher.Builder pluggedStateBatteryPluggedUsb = AtomMatcher.newBuilder() 524 .setId(pluggedStateBatteryPluggedUsbId) 525 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 526 .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER) 527 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 528 .setField(PluggedStateChanged.STATE_FIELD_NUMBER) 529 .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_USB_VALUE))); 530 531 AtomMatcher.Builder pluggedStateBatteryPluggedWireless = AtomMatcher.newBuilder() 532 .setId(pluggedStateBatteryPluggedWirelessId) 533 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 534 .setAtomId(Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER) 535 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 536 .setField(PluggedStateChanged.STATE_FIELD_NUMBER) 537 .setEqInt(BatteryPluggedStateEnum.BATTERY_PLUGGED_WIRELESS_VALUE))); 538 539 AtomMatcher.Builder pluggedStateBatteryPlugged = AtomMatcher.newBuilder() 540 .setId(pluggedStateBatteryPluggedId) 541 .setCombination(AtomMatcher.Combination.newBuilder() 542 .setOperation(LogicalOperation.OR) 543 .addMatcher(pluggedStateBatteryPluggedAcId) 544 .addMatcher(pluggedStateBatteryPluggedUsbId) 545 .addMatcher(pluggedStateBatteryPluggedWirelessId)); 546 547 Predicate.Builder deviceIsUnplugged = Predicate.newBuilder() 548 .setId(deviceIsUnpluggedId) 549 .setSimplePredicate(SimplePredicate.newBuilder() 550 .setStart(pluggedStateBatteryPluggedNoneId) 551 .setStop(pluggedStateBatteryPluggedId) 552 .setCountNesting(false)); 553 554 AtomMatcher.Builder screenStateUnknown = AtomMatcher.newBuilder() 555 .setId(screenStateUnknownId) 556 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 557 .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER) 558 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 559 .setField(ScreenStateChanged.STATE_FIELD_NUMBER) 560 .setEqInt(DisplayStateEnum.DISPLAY_STATE_UNKNOWN_VALUE))); 561 562 AtomMatcher.Builder screenStateOff = AtomMatcher.newBuilder() 563 .setId(screenStateOffId) 564 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 565 .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER) 566 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 567 .setField(ScreenStateChanged.STATE_FIELD_NUMBER) 568 .setEqInt(DisplayStateEnum.DISPLAY_STATE_OFF_VALUE))); 569 570 AtomMatcher.Builder screenStateOn = AtomMatcher.newBuilder() 571 .setId(screenStateOnId) 572 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 573 .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER) 574 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 575 .setField(ScreenStateChanged.STATE_FIELD_NUMBER) 576 .setEqInt(DisplayStateEnum.DISPLAY_STATE_ON_VALUE))); 577 578 AtomMatcher.Builder screenStateDoze = AtomMatcher.newBuilder() 579 .setId(screenStateDozeId) 580 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 581 .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER) 582 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 583 .setField(ScreenStateChanged.STATE_FIELD_NUMBER) 584 .setEqInt(DisplayStateEnum.DISPLAY_STATE_DOZE_VALUE))); 585 586 AtomMatcher.Builder screenStateDozeSuspend = AtomMatcher.newBuilder() 587 .setId(screenStateDozeSuspendId) 588 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 589 .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER) 590 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 591 .setField(ScreenStateChanged.STATE_FIELD_NUMBER) 592 .setEqInt(DisplayStateEnum.DISPLAY_STATE_DOZE_SUSPEND_VALUE))); 593 594 AtomMatcher.Builder screenStateVr = AtomMatcher.newBuilder() 595 .setId(screenStateVrId) 596 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 597 .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER) 598 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 599 .setField(ScreenStateChanged.STATE_FIELD_NUMBER) 600 .setEqInt(DisplayStateEnum.DISPLAY_STATE_VR_VALUE))); 601 602 AtomMatcher.Builder screenStateOnSuspend = AtomMatcher.newBuilder() 603 .setId(screenStateOnSuspendId) 604 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder() 605 .setAtomId(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER) 606 .addFieldValueMatcher(FieldValueMatcher.newBuilder() 607 .setField(ScreenStateChanged.STATE_FIELD_NUMBER) 608 .setEqInt(DisplayStateEnum.DISPLAY_STATE_ON_SUSPEND_VALUE))); 609 610 611 AtomMatcher.Builder screenTurnedOff = AtomMatcher.newBuilder() 612 .setId(screenTurnedOffId) 613 .setCombination(AtomMatcher.Combination.newBuilder() 614 .setOperation(LogicalOperation.OR) 615 .addMatcher(screenStateOffId) 616 .addMatcher(screenStateDozeId) 617 .addMatcher(screenStateDozeSuspendId) 618 .addMatcher(screenStateUnknownId)); 619 620 AtomMatcher.Builder screenTurnedOn = AtomMatcher.newBuilder() 621 .setId(screenTurnedOnId) 622 .setCombination(AtomMatcher.Combination.newBuilder() 623 .setOperation(LogicalOperation.OR) 624 .addMatcher(screenStateOnId) 625 .addMatcher(screenStateOnSuspendId) 626 .addMatcher(screenStateVrId)); 627 628 Predicate.Builder screenIsOff = Predicate.newBuilder() 629 .setId(screenIsOffId) 630 .setSimplePredicate(SimplePredicate.newBuilder() 631 .setStart(screenTurnedOffId) 632 .setStop(screenTurnedOnId) 633 .setCountNesting(false)); 634 635 636 Predicate.Builder screenOffBatteryOn = Predicate.newBuilder() 637 .setId(screenOffBatteryOnId) 638 .setCombination(Predicate.Combination.newBuilder() 639 .setOperation(LogicalOperation.AND) 640 .addPredicate(screenIsOffId) 641 .addPredicate(deviceIsUnpluggedId)); 642 643 StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder( 644 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 645 builder.addDurationMetric(DurationMetric.newBuilder() 646 .setId(metricId) 647 .setWhat(partialWakelockIsOnId) 648 .setCondition(screenOffBatteryOnId) 649 .setDimensionsInWhat(dimensions) 650 .setBucket(bucketsize)) 651 .addAtomMatcher(wakelockAcquire) 652 .addAtomMatcher(wakelockChangeAcquire) 653 .addAtomMatcher(wakelockRelease) 654 .addAtomMatcher(wakelockChangeRelease) 655 .addAtomMatcher(wakelockOn) 656 .addAtomMatcher(wakelockOff) 657 .addAtomMatcher(pluggedStateBatteryPluggedNone) 658 .addAtomMatcher(pluggedStateBatteryPluggedAc) 659 .addAtomMatcher(pluggedStateBatteryPluggedUsb) 660 .addAtomMatcher(pluggedStateBatteryPluggedWireless) 661 .addAtomMatcher(pluggedStateBatteryPlugged) 662 .addAtomMatcher(screenStateUnknown) 663 .addAtomMatcher(screenStateOff) 664 .addAtomMatcher(screenStateOn) 665 .addAtomMatcher(screenStateDoze) 666 .addAtomMatcher(screenStateDozeSuspend) 667 .addAtomMatcher(screenStateVr) 668 .addAtomMatcher(screenStateOnSuspend) 669 .addAtomMatcher(screenTurnedOff) 670 .addAtomMatcher(screenTurnedOn) 671 .addPredicate(wakelockPredicate) 672 .addPredicate(deviceIsUnplugged) 673 .addPredicate(screenIsOff) 674 .addPredicate(screenOffBatteryOn); 675 676 ConfigUtils.uploadConfig(getDevice(), builder); 677 } 678 resetBatteryStats()679 private void resetBatteryStats() throws Exception { 680 getDevice().executeShellCommand("dumpsys batterystats --reset"); 681 } 682 } 683