Home | History | Annotate | Download | only in atom
      1 /*
      2  * Copyright (C) 2017 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.atom;
     17 
     18 import static com.google.common.truth.Truth.assertThat;
     19 
     20 import android.os.BatteryPluggedStateEnum;
     21 import android.os.BatteryStatusEnum;
     22 import android.platform.test.annotations.RestrictedBuildTest;
     23 import android.server.DeviceIdleModeEnum;
     24 import android.view.DisplayStateEnum;
     25 
     26 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
     27 import com.android.os.AtomsProto.AppBreadcrumbReported;
     28 import com.android.os.AtomsProto.Atom;
     29 import com.android.os.AtomsProto.BatterySaverModeStateChanged;
     30 import com.android.os.AtomsProto.BuildInformation;
     31 import com.android.os.AtomsProto.ConnectivityStateChanged;
     32 import com.android.os.StatsLog.ConfigMetricsReportList;
     33 import com.android.os.StatsLog.EventMetricData;
     34 
     35 import java.util.Arrays;
     36 import java.util.HashSet;
     37 import java.util.List;
     38 import java.util.Set;
     39 
     40 /**
     41  * Statsd atom tests that are done via adb (hostside).
     42  */
     43 public class HostAtomTests extends AtomTestCase {
     44 
     45     private static final String TAG = "Statsd.HostAtomTests";
     46 
     47     // Either file must exist to read kernel wake lock stats.
     48     private static final String WAKE_LOCK_FILE = "/proc/wakelocks";
     49     private static final String WAKE_SOURCES_FILE = "/d/wakeup_sources";
     50 
     51     @Override
     52     protected void setUp() throws Exception {
     53         super.setUp();
     54     }
     55 
     56     public void testScreenStateChangedAtom() throws Exception {
     57         if (statsdDisabled()) {
     58             return;
     59         }
     60         // Setup, make sure the screen is off and turn off AoD if it is on.
     61         // AoD needs to be turned off because the screen should go into an off state. But, if AoD is
     62         // on and the device doesn't support STATE_DOZE, the screen sadly goes back to STATE_ON.
     63         String aodState = getAodState();
     64         setAodState("0");
     65         turnScreenOn();
     66         Thread.sleep(WAIT_TIME_SHORT);
     67         turnScreenOff();
     68         Thread.sleep(WAIT_TIME_SHORT);
     69 
     70         final int atomTag = Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER;
     71 
     72         Set<Integer> screenOnStates = new HashSet<>(
     73                 Arrays.asList(DisplayStateEnum.DISPLAY_STATE_ON_VALUE,
     74                         DisplayStateEnum.DISPLAY_STATE_ON_SUSPEND_VALUE,
     75                         DisplayStateEnum.DISPLAY_STATE_VR_VALUE));
     76         Set<Integer> screenOffStates = new HashSet<>(
     77                 Arrays.asList(DisplayStateEnum.DISPLAY_STATE_OFF_VALUE,
     78                         DisplayStateEnum.DISPLAY_STATE_DOZE_VALUE,
     79                         DisplayStateEnum.DISPLAY_STATE_DOZE_SUSPEND_VALUE,
     80                         DisplayStateEnum.DISPLAY_STATE_UNKNOWN_VALUE));
     81 
     82         // Add state sets to the list in order.
     83         List<Set<Integer>> stateSet = Arrays.asList(screenOnStates, screenOffStates);
     84 
     85         createAndUploadConfig(atomTag);
     86         Thread.sleep(WAIT_TIME_SHORT);
     87 
     88         // Trigger events in same order.
     89         turnScreenOn();
     90         Thread.sleep(WAIT_TIME_LONG);
     91         turnScreenOff();
     92         Thread.sleep(WAIT_TIME_LONG);
     93 
     94         // Sorted list of events in order in which they occurred.
     95         List<EventMetricData> data = getEventMetricDataList();
     96         // reset screen to on
     97         turnScreenOn();
     98         // Restores AoD to initial state.
     99         setAodState(aodState);
    100         // Assert that the events happened in the expected order.
    101         assertStatesOccurred(stateSet, data, WAIT_TIME_LONG,
    102                 atom -> atom.getScreenStateChanged().getState().getNumber());
    103     }
    104 
    105     public void testChargingStateChangedAtom() throws Exception {
    106         if (statsdDisabled()) {
    107             return;
    108         }
    109         if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
    110         // Setup, set charging state to full.
    111         setChargingState(5);
    112         Thread.sleep(WAIT_TIME_SHORT);
    113 
    114         final int atomTag = Atom.CHARGING_STATE_CHANGED_FIELD_NUMBER;
    115 
    116         Set<Integer> batteryUnknownStates = new HashSet<>(
    117                 Arrays.asList(BatteryStatusEnum.BATTERY_STATUS_UNKNOWN_VALUE));
    118         Set<Integer> batteryChargingStates = new HashSet<>(
    119                 Arrays.asList(BatteryStatusEnum.BATTERY_STATUS_CHARGING_VALUE));
    120         Set<Integer> batteryDischargingStates = new HashSet<>(
    121                 Arrays.asList(BatteryStatusEnum.BATTERY_STATUS_DISCHARGING_VALUE));
    122         Set<Integer> batteryNotChargingStates = new HashSet<>(
    123                 Arrays.asList(BatteryStatusEnum.BATTERY_STATUS_NOT_CHARGING_VALUE));
    124         Set<Integer> batteryFullStates = new HashSet<>(
    125                 Arrays.asList(BatteryStatusEnum.BATTERY_STATUS_FULL_VALUE));
    126 
    127         // Add state sets to the list in order.
    128         List<Set<Integer>> stateSet = Arrays.asList(batteryUnknownStates, batteryChargingStates,
    129                 batteryDischargingStates, batteryNotChargingStates, batteryFullStates);
    130 
    131         createAndUploadConfig(atomTag);
    132         Thread.sleep(WAIT_TIME_SHORT);
    133 
    134         // Trigger events in same order.
    135         setChargingState(1);
    136         Thread.sleep(WAIT_TIME_SHORT);
    137         setChargingState(2);
    138         Thread.sleep(WAIT_TIME_SHORT);
    139         setChargingState(3);
    140         Thread.sleep(WAIT_TIME_SHORT);
    141         setChargingState(4);
    142         Thread.sleep(WAIT_TIME_SHORT);
    143         setChargingState(5);
    144         Thread.sleep(WAIT_TIME_SHORT);
    145 
    146         // Sorted list of events in order in which they occurred.
    147         List<EventMetricData> data = getEventMetricDataList();
    148 
    149         // Unfreeze battery state after test
    150         resetBatteryStatus();
    151         Thread.sleep(WAIT_TIME_SHORT);
    152 
    153         // Assert that the events happened in the expected order.
    154         assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT,
    155                 atom -> atom.getChargingStateChanged().getState().getNumber());
    156     }
    157 
    158     public void testPluggedStateChangedAtom() throws Exception {
    159         if (statsdDisabled()) {
    160             return;
    161         }
    162         if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
    163         // Setup, unplug device.
    164         unplugDevice();
    165         Thread.sleep(WAIT_TIME_SHORT);
    166 
    167         final int atomTag = Atom.PLUGGED_STATE_CHANGED_FIELD_NUMBER;
    168 
    169         Set<Integer> unpluggedStates = new HashSet<>(
    170                 Arrays.asList(BatteryPluggedStateEnum.BATTERY_PLUGGED_NONE_VALUE));
    171         Set<Integer> acStates = new HashSet<>(
    172                 Arrays.asList(BatteryPluggedStateEnum.BATTERY_PLUGGED_AC_VALUE));
    173         Set<Integer> usbStates = new HashSet<>(
    174                 Arrays.asList(BatteryPluggedStateEnum.BATTERY_PLUGGED_USB_VALUE));
    175         Set<Integer> wirelessStates = new HashSet<>(
    176                 Arrays.asList(BatteryPluggedStateEnum.BATTERY_PLUGGED_WIRELESS_VALUE));
    177 
    178         // Add state sets to the list in order.
    179         List<Set<Integer>> stateSet = Arrays.asList(acStates, unpluggedStates, usbStates,
    180                 unpluggedStates, wirelessStates, unpluggedStates);
    181 
    182         createAndUploadConfig(atomTag);
    183         Thread.sleep(WAIT_TIME_SHORT);
    184 
    185         // Trigger events in same order.
    186         plugInAc();
    187         Thread.sleep(WAIT_TIME_SHORT);
    188         unplugDevice();
    189         Thread.sleep(WAIT_TIME_SHORT);
    190         plugInUsb();
    191         Thread.sleep(WAIT_TIME_SHORT);
    192         unplugDevice();
    193         Thread.sleep(WAIT_TIME_SHORT);
    194         plugInWireless();
    195         Thread.sleep(WAIT_TIME_SHORT);
    196         unplugDevice();
    197         Thread.sleep(WAIT_TIME_SHORT);
    198 
    199         // Sorted list of events in order in which they occurred.
    200         List<EventMetricData> data = getEventMetricDataList();
    201 
    202         // Unfreeze battery state after test
    203         resetBatteryStatus();
    204         Thread.sleep(WAIT_TIME_SHORT);
    205 
    206         // Assert that the events happened in the expected order.
    207         assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT,
    208                 atom -> atom.getPluggedStateChanged().getState().getNumber());
    209     }
    210 
    211     public void testBatteryLevelChangedAtom() throws Exception {
    212         if (statsdDisabled()) {
    213             return;
    214         }
    215         if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
    216         // Setup, set battery level to full.
    217         setBatteryLevel(100);
    218         Thread.sleep(WAIT_TIME_SHORT);
    219 
    220         final int atomTag = Atom.BATTERY_LEVEL_CHANGED_FIELD_NUMBER;
    221 
    222         Set<Integer> batteryLow = new HashSet<>(Arrays.asList(2));
    223         Set<Integer> battery25p = new HashSet<>(Arrays.asList(25));
    224         Set<Integer> battery50p = new HashSet<>(Arrays.asList(50));
    225         Set<Integer> battery75p = new HashSet<>(Arrays.asList(75));
    226         Set<Integer> batteryFull = new HashSet<>(Arrays.asList(100));
    227 
    228         // Add state sets to the list in order.
    229         List<Set<Integer>> stateSet = Arrays.asList(batteryLow, battery25p, battery50p,
    230                 battery75p, batteryFull);
    231 
    232         createAndUploadConfig(atomTag);
    233         Thread.sleep(WAIT_TIME_SHORT);
    234 
    235         // Trigger events in same order.
    236         setBatteryLevel(2);
    237         Thread.sleep(WAIT_TIME_SHORT);
    238         setBatteryLevel(25);
    239         Thread.sleep(WAIT_TIME_SHORT);
    240         setBatteryLevel(50);
    241         Thread.sleep(WAIT_TIME_SHORT);
    242         setBatteryLevel(75);
    243         Thread.sleep(WAIT_TIME_SHORT);
    244         setBatteryLevel(100);
    245         Thread.sleep(WAIT_TIME_SHORT);
    246 
    247         // Sorted list of events in order in which they occurred.
    248         List<EventMetricData> data = getEventMetricDataList();
    249 
    250         // Unfreeze battery state after test
    251         resetBatteryStatus();
    252         Thread.sleep(WAIT_TIME_SHORT);
    253 
    254         // Assert that the events happened in the expected order.
    255         assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT,
    256                 atom -> atom.getBatteryLevelChanged().getBatteryLevel());
    257     }
    258 
    259     public void testDeviceIdleModeStateChangedAtom() throws Exception {
    260         if (statsdDisabled()) {
    261             return;
    262         }
    263         // Setup, leave doze mode.
    264         leaveDozeMode();
    265         Thread.sleep(WAIT_TIME_SHORT);
    266 
    267         final int atomTag = Atom.DEVICE_IDLE_MODE_STATE_CHANGED_FIELD_NUMBER;
    268 
    269         Set<Integer> dozeOff = new HashSet<>(
    270                 Arrays.asList(DeviceIdleModeEnum.DEVICE_IDLE_MODE_OFF_VALUE));
    271         Set<Integer> dozeLight = new HashSet<>(
    272                 Arrays.asList(DeviceIdleModeEnum.DEVICE_IDLE_MODE_LIGHT_VALUE));
    273         Set<Integer> dozeDeep = new HashSet<>(
    274                 Arrays.asList(DeviceIdleModeEnum.DEVICE_IDLE_MODE_DEEP_VALUE));
    275 
    276         // Add state sets to the list in order.
    277         List<Set<Integer>> stateSet = Arrays.asList(dozeLight, dozeDeep, dozeOff);
    278 
    279         createAndUploadConfig(atomTag);
    280         Thread.sleep(WAIT_TIME_SHORT);
    281 
    282         // Trigger events in same order.
    283         enterDozeModeLight();
    284         Thread.sleep(WAIT_TIME_SHORT);
    285         enterDozeModeDeep();
    286         Thread.sleep(WAIT_TIME_SHORT);
    287         leaveDozeMode();
    288         Thread.sleep(WAIT_TIME_SHORT);
    289 
    290         // Sorted list of events in order in which they occurred.
    291         List<EventMetricData> data = getEventMetricDataList();;
    292 
    293         // Assert that the events happened in the expected order.
    294         assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT,
    295                 atom -> atom.getDeviceIdleModeStateChanged().getState().getNumber());
    296     }
    297 
    298     public void testBatterySaverModeStateChangedAtom() throws Exception {
    299         if (statsdDisabled()) {
    300             return;
    301         }
    302         if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
    303         // Setup, turn off battery saver.
    304         turnBatterySaverOff();
    305         Thread.sleep(WAIT_TIME_SHORT);
    306 
    307         final int atomTag = Atom.BATTERY_SAVER_MODE_STATE_CHANGED_FIELD_NUMBER;
    308 
    309         Set<Integer> batterySaverOn = new HashSet<>(
    310                 Arrays.asList(BatterySaverModeStateChanged.State.ON_VALUE));
    311         Set<Integer> batterySaverOff = new HashSet<>(
    312                 Arrays.asList(BatterySaverModeStateChanged.State.OFF_VALUE));
    313 
    314         // Add state sets to the list in order.
    315         List<Set<Integer>> stateSet = Arrays.asList(batterySaverOn, batterySaverOff);
    316 
    317         createAndUploadConfig(atomTag);
    318         Thread.sleep(WAIT_TIME_SHORT);
    319 
    320         // Trigger events in same order.
    321         turnBatterySaverOn();
    322         Thread.sleep(WAIT_TIME_LONG);
    323         turnBatterySaverOff();
    324         Thread.sleep(WAIT_TIME_LONG);
    325 
    326         // Sorted list of events in order in which they occurred.
    327         List<EventMetricData> data = getEventMetricDataList();
    328 
    329         // Assert that the events happened in the expected order.
    330         assertStatesOccurred(stateSet, data, WAIT_TIME_LONG,
    331                 atom -> atom.getBatterySaverModeStateChanged().getState().getNumber());
    332     }
    333 
    334     @RestrictedBuildTest
    335     public void testRemainingBatteryCapacity() throws Exception {
    336         if (statsdDisabled()) {
    337             return;
    338         }
    339         if (!hasFeature(FEATURE_WATCH, false)) return;
    340         if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
    341         StatsdConfig.Builder config = getPulledConfig();
    342         addGaugeAtomWithDimensions(config, Atom.REMAINING_BATTERY_CAPACITY_FIELD_NUMBER, null);
    343 
    344         uploadConfig(config);
    345 
    346         Thread.sleep(WAIT_TIME_LONG);
    347         setAppBreadcrumbPredicate();
    348         Thread.sleep(WAIT_TIME_LONG);
    349 
    350         List<Atom> data = getGaugeMetricDataList();
    351 
    352         assertTrue(data.size() > 0);
    353         Atom atom = data.get(0);
    354         assertTrue(atom.getRemainingBatteryCapacity().hasChargeMicroAmpereHour());
    355         if (hasBattery()) {
    356             assertTrue(atom.getRemainingBatteryCapacity().getChargeMicroAmpereHour() > 0);
    357         }
    358     }
    359 
    360     @RestrictedBuildTest
    361     public void testFullBatteryCapacity() throws Exception {
    362         if (statsdDisabled()) {
    363             return;
    364         }
    365         if (!hasFeature(FEATURE_WATCH, false)) return;
    366         if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
    367         StatsdConfig.Builder config = getPulledConfig();
    368         addGaugeAtomWithDimensions(config, Atom.FULL_BATTERY_CAPACITY_FIELD_NUMBER, null);
    369 
    370         uploadConfig(config);
    371 
    372         Thread.sleep(WAIT_TIME_LONG);
    373         setAppBreadcrumbPredicate();
    374         Thread.sleep(WAIT_TIME_LONG);
    375 
    376         List<Atom> data = getGaugeMetricDataList();
    377 
    378         assertTrue(data.size() > 0);
    379         Atom atom = data.get(0);
    380         assertTrue(atom.getFullBatteryCapacity().hasCapacityMicroAmpereHour());
    381         if (hasBattery()) {
    382             assertTrue(atom.getFullBatteryCapacity().getCapacityMicroAmpereHour() > 0);
    383         }
    384     }
    385 
    386     public void testBatteryVoltage() throws Exception {
    387         if (statsdDisabled()) {
    388             return;
    389         }
    390         if (!hasFeature(FEATURE_WATCH, false)) return;
    391         StatsdConfig.Builder config = getPulledConfig();
    392         addGaugeAtomWithDimensions(config, Atom.BATTERY_VOLTAGE_FIELD_NUMBER, null);
    393 
    394         uploadConfig(config);
    395 
    396         Thread.sleep(WAIT_TIME_LONG);
    397         setAppBreadcrumbPredicate();
    398         Thread.sleep(WAIT_TIME_LONG);
    399 
    400         List<Atom> data = getGaugeMetricDataList();
    401 
    402         assertTrue(data.size() > 0);
    403         Atom atom = data.get(0);
    404         assertTrue(atom.getBatteryVoltage().hasVoltageMillivolt());
    405         if (hasBattery()) {
    406             assertTrue(atom.getBatteryVoltage().getVoltageMillivolt() > 0);
    407         }
    408     }
    409 
    410     // This test is for the pulled battery level atom.
    411     public void testBatteryLevel() throws Exception {
    412         if (statsdDisabled()) {
    413             return;
    414         }
    415         if (!hasFeature(FEATURE_WATCH, false)) return;
    416         StatsdConfig.Builder config = getPulledConfig();
    417         addGaugeAtomWithDimensions(config, Atom.BATTERY_LEVEL_FIELD_NUMBER, null);
    418 
    419         uploadConfig(config);
    420 
    421         Thread.sleep(WAIT_TIME_LONG);
    422         setAppBreadcrumbPredicate();
    423         Thread.sleep(WAIT_TIME_LONG);
    424 
    425         List<Atom> data = getGaugeMetricDataList();
    426 
    427         assertTrue(data.size() > 0);
    428         Atom atom = data.get(0);
    429         assertTrue(atom.getBatteryLevel().hasBatteryLevel());
    430         if (hasBattery()) {
    431             assertTrue(atom.getBatteryLevel().getBatteryLevel() > 0);
    432             assertTrue(atom.getBatteryLevel().getBatteryLevel() <= 100);
    433         }
    434     }
    435 
    436     // This test is for the pulled battery charge count atom.
    437     public void testBatteryCycleCount() throws Exception {
    438         if (statsdDisabled()) {
    439             return;
    440         }
    441         if (!hasFeature(FEATURE_WATCH, false)) return;
    442         StatsdConfig.Builder config = getPulledConfig();
    443         addGaugeAtomWithDimensions(config, Atom.BATTERY_CYCLE_COUNT_FIELD_NUMBER, null);
    444 
    445         uploadConfig(config);
    446 
    447         Thread.sleep(WAIT_TIME_LONG);
    448         setAppBreadcrumbPredicate();
    449         Thread.sleep(WAIT_TIME_LONG);
    450 
    451         List<Atom> data = getGaugeMetricDataList();
    452 
    453         assertTrue(data.size() > 0);
    454         Atom atom = data.get(0);
    455         assertTrue(atom.getBatteryCycleCount().hasCycleCount());
    456         if (hasBattery()) {
    457             assertTrue(atom.getBatteryCycleCount().getCycleCount() >= 0);
    458         }
    459     }
    460 
    461     public void testKernelWakelock() throws Exception {
    462         if (statsdDisabled() || !kernelWakelockStatsExist()) {
    463             return;
    464         }
    465         StatsdConfig.Builder config = getPulledConfig();
    466         addGaugeAtomWithDimensions(config, Atom.KERNEL_WAKELOCK_FIELD_NUMBER, null);
    467 
    468         uploadConfig(config);
    469 
    470         Thread.sleep(WAIT_TIME_LONG);
    471         setAppBreadcrumbPredicate();
    472         Thread.sleep(WAIT_TIME_LONG);
    473 
    474         List<Atom> data = getGaugeMetricDataList();
    475 
    476         Atom atom = data.get(0);
    477         assertTrue(!atom.getKernelWakelock().getName().equals(""));
    478         assertTrue(atom.getKernelWakelock().hasCount());
    479         assertTrue(atom.getKernelWakelock().hasVersion());
    480         assertTrue(atom.getKernelWakelock().getVersion() > 0);
    481         assertTrue(atom.getKernelWakelock().hasTimeMicros());
    482     }
    483 
    484     // Returns true iff either |WAKE_LOCK_FILE| or |WAKE_SOURCES_FILE| exists.
    485     private boolean kernelWakelockStatsExist() {
    486       try {
    487         return doesFileExist(WAKE_LOCK_FILE) || doesFileExist(WAKE_SOURCES_FILE);
    488       } catch(Exception e) {
    489         return false;
    490       }
    491     }
    492 
    493     public void testWifiActivityInfo() throws Exception {
    494         if (statsdDisabled()) {
    495             return;
    496         }
    497         if (!hasFeature(FEATURE_WIFI, true)) return;
    498         if (!hasFeature(FEATURE_WATCH, false)) return;
    499         if (!checkDeviceFor("checkWifiEnhancedPowerReportingSupported")) return;
    500 
    501         StatsdConfig.Builder config = getPulledConfig();
    502         addGaugeAtomWithDimensions(config, Atom.WIFI_ACTIVITY_INFO_FIELD_NUMBER, null);
    503 
    504         uploadConfig(config);
    505 
    506         Thread.sleep(WAIT_TIME_LONG);
    507         setAppBreadcrumbPredicate();
    508         Thread.sleep(WAIT_TIME_LONG);
    509 
    510         List<Atom> dataList = getGaugeMetricDataList();
    511 
    512         for (Atom atom: dataList) {
    513             assertTrue(atom.getWifiActivityInfo().getTimestampMillis() > 0);
    514             assertTrue(atom.getWifiActivityInfo().getStackState() >= 0);
    515             assertTrue(atom.getWifiActivityInfo().getControllerIdleTimeMillis() > 0);
    516             assertTrue(atom.getWifiActivityInfo().getControllerTxTimeMillis() >= 0);
    517             assertTrue(atom.getWifiActivityInfo().getControllerRxTimeMillis() >= 0);
    518             assertTrue(atom.getWifiActivityInfo().getControllerEnergyUsed() >= 0);
    519         }
    520     }
    521 
    522     public void testBuildInformation() throws Exception {
    523         if (statsdDisabled()) {
    524             return;
    525         }
    526 
    527         StatsdConfig.Builder config = getPulledConfig();
    528         addGaugeAtomWithDimensions(config, Atom.BUILD_INFORMATION_FIELD_NUMBER, null);
    529         uploadConfig(config);
    530 
    531         Thread.sleep(WAIT_TIME_LONG);
    532         setAppBreadcrumbPredicate();
    533         Thread.sleep(WAIT_TIME_LONG);
    534 
    535         List<Atom> data = getGaugeMetricDataList();
    536         assertTrue(data.size() > 0);
    537         BuildInformation atom = data.get(0).getBuildInformation();
    538         assertEquals(getProperty("ro.product.brand"),             atom.getBrand());
    539         assertEquals(getProperty("ro.product.name"),              atom.getProduct());
    540         assertEquals(getProperty("ro.product.device"),            atom.getDevice());
    541         assertEquals(getProperty("ro.build.version.release"),     atom.getVersionRelease());
    542         assertEquals(getProperty("ro.build.id"),                  atom.getId());
    543         assertEquals(getProperty("ro.build.version.incremental"), atom.getVersionIncremental());
    544         assertEquals(getProperty("ro.build.type"),                atom.getType());
    545         assertEquals(getProperty("ro.build.tags"),                atom.getTags());
    546     }
    547 
    548     public void testOnDevicePowerMeasurement() throws Exception {
    549         if (!OPTIONAL_TESTS_ENABLED) return;
    550         if (statsdDisabled()) {
    551             return;
    552         }
    553 
    554         StatsdConfig.Builder config = getPulledConfig();
    555         addGaugeAtomWithDimensions(config, Atom.ON_DEVICE_POWER_MEASUREMENT_FIELD_NUMBER, null);
    556 
    557         uploadConfig(config);
    558 
    559         Thread.sleep(WAIT_TIME_LONG);
    560         setAppBreadcrumbPredicate();
    561         Thread.sleep(WAIT_TIME_LONG);
    562 
    563         List<Atom> dataList = getGaugeMetricDataList();
    564 
    565         for (Atom atom: dataList) {
    566             assertTrue(atom.getOnDevicePowerMeasurement().getMeasurementTimestampMillis() >= 0);
    567             assertTrue(atom.getOnDevicePowerMeasurement().getEnergyMicrowattSecs() >= 0);
    568         }
    569     }
    570 
    571     // Explicitly tests if the adb command to log a breadcrumb is working.
    572     public void testBreadcrumbAdb() throws Exception {
    573         if (statsdDisabled()) {
    574             return;
    575         }
    576         final int atomTag = Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER;
    577         createAndUploadConfig(atomTag);
    578         Thread.sleep(WAIT_TIME_SHORT);
    579 
    580         doAppBreadcrumbReportedStart(1);
    581         Thread.sleep(WAIT_TIME_SHORT);
    582 
    583         List<EventMetricData> data = getEventMetricDataList();
    584         AppBreadcrumbReported atom = data.get(0).getAtom().getAppBreadcrumbReported();
    585         assertTrue(atom.getLabel() == 1);
    586         assertTrue(atom.getState().getNumber() == AppBreadcrumbReported.State.START_VALUE);
    587     }
    588 
    589     // Test dumpsys stats --proto.
    590     public void testDumpsysStats() throws Exception {
    591         if (statsdDisabled()) {
    592             return;
    593         }
    594         final int atomTag = Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER;
    595         createAndUploadConfig(atomTag);
    596         Thread.sleep(WAIT_TIME_SHORT);
    597 
    598         doAppBreadcrumbReportedStart(1);
    599         Thread.sleep(WAIT_TIME_SHORT);
    600 
    601         // Get the stats incident section.
    602         List<ConfigMetricsReportList> listList = getReportsFromStatsDataDumpProto();
    603         assertTrue(listList.size() > 0);
    604 
    605         // Extract the relevent report from the incident section.
    606         ConfigMetricsReportList ourList = null;
    607         int hostUid = getHostUid();
    608         for (ConfigMetricsReportList list : listList) {
    609             ConfigMetricsReportList.ConfigKey configKey = list.getConfigKey();
    610             if (configKey.getUid() == hostUid && configKey.getId() == CONFIG_ID) {
    611                 ourList = list;
    612                 break;
    613             }
    614         }
    615         assertNotNull("Could not find list for uid=" + hostUid
    616                 + " id=" + CONFIG_ID, ourList);
    617 
    618         // Make sure that the report is correct.
    619         List<EventMetricData> data = getEventMetricDataList(ourList);
    620         AppBreadcrumbReported atom = data.get(0).getAtom().getAppBreadcrumbReported();
    621         assertTrue(atom.getLabel() == 1);
    622         assertTrue(atom.getState().getNumber() == AppBreadcrumbReported.State.START_VALUE);
    623     }
    624 
    625     public void testConnectivityStateChange() throws Exception {
    626         if (statsdDisabled()) {
    627             return;
    628         }
    629         if (!hasFeature(FEATURE_WIFI, true)) return;
    630         if (!hasFeature(FEATURE_WATCH, false)) return;
    631 
    632         final int atomTag = Atom.CONNECTIVITY_STATE_CHANGED_FIELD_NUMBER;
    633         createAndUploadConfig(atomTag);
    634         Thread.sleep(WAIT_TIME_SHORT);
    635 
    636         turnOnAirplaneMode();
    637         // wait long enough for airplane mode events to propagate.
    638         Thread.sleep(1_200);
    639         turnOffAirplaneMode();
    640         // wait long enough for the device to restore connection
    641         Thread.sleep(13_000);
    642 
    643         List<EventMetricData> data = getEventMetricDataList();
    644         // at least 1 disconnect and 1 connect
    645         assertThat(data.size()).isAtLeast(2);
    646         boolean foundDisconnectEvent = false;
    647         boolean foundConnectEvent = false;
    648         for (EventMetricData d : data) {
    649             ConnectivityStateChanged atom = d.getAtom().getConnectivityStateChanged();
    650             if(atom.getState().getNumber()
    651                     == ConnectivityStateChanged.State.DISCONNECTED_VALUE) {
    652                 foundDisconnectEvent = true;
    653             }
    654             if(atom.getState().getNumber()
    655                     == ConnectivityStateChanged.State.CONNECTED_VALUE) {
    656                 foundConnectEvent = true;
    657             }
    658         }
    659         assertTrue(foundConnectEvent && foundDisconnectEvent);
    660     }
    661 }
    662