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