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 com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
     19 import com.android.internal.os.StatsdConfigProto.MessageMatcher;
     20 import com.android.internal.os.StatsdConfigProto.Position;
     21 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
     22 import com.android.os.StatsLog.EventMetricData;
     23 import com.android.tradefed.log.LogUtil;
     24 
     25 import java.util.Arrays;
     26 import java.util.List;
     27 
     28 /**
     29  * Base class for testing Statsd atoms that report a uid. Tests are performed via a device-side app.
     30  */
     31 public class DeviceAtomTestCase extends AtomTestCase {
     32 
     33     protected static final String DEVICE_SIDE_TEST_APK = "CtsStatsdApp.apk";
     34     protected static final String DEVICE_SIDE_TEST_PACKAGE =
     35             "com.android.server.cts.device.statsd";
     36     protected static final long DEVICE_SIDE_TEST_PKG_HASH =
     37             Long.parseUnsignedLong("15694052924544098582");
     38 
     39     protected static final String CONFIG_NAME = "cts_config";
     40 
     41     @Override
     42     protected void setUp() throws Exception {
     43         super.setUp();
     44         getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
     45         installTestApp();
     46     }
     47 
     48     @Override
     49     protected void tearDown() throws Exception {
     50         getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
     51         super.tearDown();
     52     }
     53 
     54     /**
     55      * Performs a device-side test by calling a method on the app and returns its stats events.
     56      * @param methodName the name of the method in the app's AtomTests to perform
     57      * @param atom atom tag (from atoms.proto)
     58      * @param key atom's field corresponding to state
     59      * @param stateOn 'on' value
     60      * @param stateOff 'off' value
     61      * @param minTimeDiffMs max allowed time between start and stop
     62      * @param maxTimeDiffMs min allowed time between start and stop
     63      * @param demandExactlyTwo whether there must be precisely two events logged (1 start, 1 stop)
     64      * @return list of events with the app's uid matching the configuration defined by the params.
     65      */
     66     protected List<EventMetricData> doDeviceMethodOnOff(
     67             String methodName, int atom, int key, int stateOn, int stateOff,
     68             int minTimeDiffMs, int maxTimeDiffMs, boolean demandExactlyTwo) throws Exception {
     69         StatsdConfig.Builder conf = createConfigBuilder();
     70         addAtomEvent(conf, atom, createFvm(key).setEqInt(stateOn));
     71         addAtomEvent(conf, atom, createFvm(key).setEqInt(stateOff));
     72         List<EventMetricData> data = doDeviceMethod(methodName, conf);
     73 
     74         if (demandExactlyTwo) {
     75             assertTrue(data.size() == 2);
     76         } else {
     77             assertTrue(data.size() >= 2);
     78         }
     79         assertTimeDiffBetween(data.get(0), data.get(1), minTimeDiffMs, maxTimeDiffMs);
     80         return data;
     81     }
     82 
     83     /**
     84      *
     85      * @param methodName the name of the method in the app's AtomTests to perform
     86      * @param cfg statsd configuration
     87      * @return list of events with the app's uid matching the configuration.
     88      */
     89     protected List<EventMetricData> doDeviceMethod(String methodName, StatsdConfig.Builder cfg)
     90             throws Exception {
     91         removeConfig(CONFIG_ID);
     92         getReportList();  // Clears previous data on disk.
     93         uploadConfig(cfg);
     94         int appUid = getUid();
     95         LogUtil.CLog.d("\nPerforming device-side test of " + methodName + " for uid " + appUid);
     96         runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", methodName);
     97 
     98         return getEventMetricDataList();
     99     }
    100 
    101     protected void createAndUploadConfig(int atomTag, boolean useAttribution) throws Exception {
    102         StatsdConfig.Builder conf = createConfigBuilder();
    103         addAtomEvent(conf, atomTag, useAttribution);
    104         uploadConfig(conf);
    105     }
    106 
    107     /**
    108      * Adds an event to the config for an atom that matches the given key AND has the app's uid.
    109      * @param conf configuration
    110      * @param atomTag atom tag (from atoms.proto)
    111      * @param fvm FieldValueMatcher.Builder for the relevant key
    112      */
    113     @Override
    114     protected void addAtomEvent(StatsdConfig.Builder conf, int atomTag, FieldValueMatcher.Builder fvm)
    115             throws Exception {
    116 
    117         final int UID_KEY = 1;
    118         FieldValueMatcher.Builder fvmUid = createAttributionFvm(UID_KEY);
    119         addAtomEvent(conf, atomTag, Arrays.asList(fvm, fvmUid));
    120     }
    121 
    122     /**
    123      * Adds an event to the config for an atom that matches the app's uid.
    124      * @param conf configuration
    125      * @param atomTag atom tag (from atoms.proto)
    126      * @param useAttribution if the atom has a uid or AttributionNode
    127      */
    128     protected void addAtomEvent(StatsdConfig.Builder conf, int atomTag,
    129             boolean useAttribution) throws Exception {
    130         final int UID_KEY = 1;
    131         FieldValueMatcher.Builder fvmUid;
    132         if (useAttribution) {
    133             fvmUid = createAttributionFvm(UID_KEY);
    134         } else {
    135             fvmUid = createFvm(UID_KEY).setEqInt(getUid());
    136         }
    137         addAtomEvent(conf, atomTag, Arrays.asList(fvmUid));
    138     }
    139 
    140     /**
    141      * Creates a FieldValueMatcher for atoms that use AttributionNode
    142      */
    143     protected FieldValueMatcher.Builder createAttributionFvm(int field) {
    144         final int ATTRIBUTION_NODE_UID_KEY = 1;
    145         return createFvm(field).setPosition(Position.ANY)
    146                 .setMatchesTuple(MessageMatcher.newBuilder()
    147                         .addFieldValueMatcher(createFvm(ATTRIBUTION_NODE_UID_KEY)
    148                                 .setEqString(DEVICE_SIDE_TEST_PACKAGE)));
    149     }
    150 
    151     /**
    152      * Gets the uid of the test app.
    153      */
    154     protected int getUid() throws Exception {
    155         String uidLine = getDevice().executeShellCommand("cmd package list packages -U "
    156                 + DEVICE_SIDE_TEST_PACKAGE);
    157         String[] uidLineParts = uidLine.split(":");
    158         // 3rd entry is package uid
    159         assertTrue(uidLineParts.length > 2);
    160         int uid = Integer.parseInt(uidLineParts[2].trim());
    161         assertTrue(uid > 10000);
    162         return uid;
    163     }
    164 
    165     /**
    166      * Installs the test apk.
    167      */
    168     protected void installTestApp() throws Exception {
    169         installPackage(DEVICE_SIDE_TEST_APK, true);
    170         LogUtil.CLog.i("Installing device-side test app with uid " + getUid());
    171         allowBackgroundServices();
    172     }
    173 
    174     /**
    175      * Required to successfully start a background service from adb in O.
    176      */
    177     protected void allowBackgroundServices() throws Exception {
    178         getDevice().executeShellCommand(String.format(
    179                 "cmd deviceidle tempwhitelist %s", DEVICE_SIDE_TEST_PACKAGE));
    180     }
    181 
    182     /** Make the test app standby-active so it can run syncs and jobs immediately. */
    183     protected void allowImmediateSyncs() throws Exception {
    184         getDevice().executeShellCommand("am set-standby-bucket "
    185                 + DEVICE_SIDE_TEST_PACKAGE + " active");
    186     }
    187 
    188     /**
    189      * Runs the specified activity.
    190      */
    191     protected void runActivity(String activity, String actionKey, String actionValue)
    192             throws Exception {
    193         runActivity(activity, actionKey, actionValue, WAIT_TIME_LONG);
    194     }
    195 
    196     /**
    197      * Runs the specified activity.
    198      */
    199     protected void runActivity(String activity, String actionKey, String actionValue,
    200             long waitTime) throws Exception {
    201         String intentString = null;
    202         if (actionKey != null && actionValue != null) {
    203             intentString = actionKey + " " + actionValue;
    204         }
    205         if (intentString == null) {
    206             getDevice().executeShellCommand(
    207                     "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity);
    208         } else {
    209             getDevice().executeShellCommand(
    210                     "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity + " -e " +
    211                             intentString);
    212         }
    213 
    214         Thread.sleep(waitTime);
    215         getDevice().executeShellCommand(
    216                 "am force-stop " + DEVICE_SIDE_TEST_PACKAGE);
    217 
    218         Thread.sleep(WAIT_TIME_SHORT);
    219     }
    220 
    221     protected void resetBatteryStats() throws Exception {
    222         getDevice().executeShellCommand("dumpsys batterystats --reset");
    223     }
    224 }
    225