Home | History | Annotate | Download | only in functional
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.systemmetrics.functional;
     18 
     19 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
     20 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
     21 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
     22 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_PROCESS_RUNNING;
     23 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN;
     24 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;
     25 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
     26 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
     27 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
     28 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
     29 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
     30 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
     31 import static junit.framework.TestCase.assertTrue;
     32 import static org.junit.Assert.assertEquals;
     33 import static org.junit.Assert.assertNotNull;
     34 
     35 import android.content.Context;
     36 import android.content.Intent;
     37 import android.metrics.LogMaker;
     38 import android.metrics.MetricsReader;
     39 import android.os.SystemClock;
     40 import android.support.test.InstrumentationRegistry;
     41 import android.support.test.filters.MediumTest;
     42 import android.support.test.metricshelper.MetricsAsserts;
     43 import android.support.test.runner.AndroidJUnit4;
     44 import android.support.test.uiautomator.By;
     45 import android.support.test.uiautomator.UiDevice;
     46 import android.support.test.uiautomator.Until;
     47 import android.text.TextUtils;
     48 
     49 import org.junit.After;
     50 import org.junit.Before;
     51 import org.junit.Test;
     52 import org.junit.runner.RunWith;
     53 
     54 import java.util.Queue;
     55 
     56 /**
     57  * runtest --path platform_testing/tests/functional/systemmetrics/
     58  */
     59 @MediumTest
     60 @RunWith(AndroidJUnit4.class)
     61 public class AppStartTests {
     62     private static final String LOG_TAG = AppStartTests.class.getSimpleName();
     63     private static final String SETTINGS_PACKAGE = "com.android.settings";
     64     private static final int LONG_TIMEOUT_MS = 2000;
     65     private UiDevice mDevice = null;
     66     private Context mContext;
     67     private MetricsReader mMetricsReader;
     68     private int mPreUptime;
     69 
     70     @Before
     71     public void setUp() throws Exception {
     72         mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
     73         mContext = InstrumentationRegistry.getTargetContext();
     74         mDevice.setOrientationNatural();
     75         mMetricsReader = new MetricsReader();
     76         mMetricsReader.checkpoint(); // clear out old logs
     77         mPreUptime = (int) (SystemClock.uptimeMillis() / 1000);
     78     }
     79 
     80     @After
     81     public void tearDown() throws Exception {
     82         mDevice.unfreezeRotation();
     83         mContext.startActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
     84         mDevice.waitForIdle();
     85     }
     86 
     87     @Test
     88     public void testStartApp() throws Exception {
     89         Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(SETTINGS_PACKAGE);
     90 
     91         // Clear out any previous instances
     92         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
     93 
     94         assertNotNull("component name is null", intent.getComponent());
     95         String className = intent.getComponent().getClassName();
     96         String packageName = intent.getComponent().getPackageName();
     97         assertTrue("className is empty", !TextUtils.isEmpty(className));
     98         assertTrue("packageName is empty", !TextUtils.isEmpty(packageName));
     99 
    100 
    101         mContext.startActivity(intent);
    102         mDevice.wait(Until.hasObject(By.pkg(SETTINGS_PACKAGE).depth(0)), LONG_TIMEOUT_MS);
    103 
    104         int postUptime = (int) (SystemClock.uptimeMillis() / 1000);
    105 
    106         Queue<LogMaker> startLogs = MetricsAsserts.findMatchingLogs(mMetricsReader,
    107                 new LogMaker(APP_TRANSITION));
    108         boolean found = false;
    109         for (LogMaker log : startLogs) {
    110             String actualClassName = (String) log.getTaggedData(
    111                     FIELD_CLASS_NAME);
    112             String actualPackageName = log.getPackageName();
    113             if (className.equals(actualClassName) && packageName.equals(actualPackageName)) {
    114                 found = true;
    115                 int startUptime = ((Number)
    116                         log.getTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS))
    117                         .intValue();
    118                 assertTrue("must be either cold or warm launch",
    119                         TYPE_TRANSITION_COLD_LAUNCH == log.getType()
    120                                 || TYPE_TRANSITION_WARM_LAUNCH == log.getType());
    121                 assertTrue("reported uptime should be after the app was started",
    122                         mPreUptime <= startUptime);
    123                 assertTrue("reported uptime should be before assertion time",
    124                         startUptime <= postUptime);
    125                 assertNotNull("log should have delay",
    126                         log.getTaggedData(APP_TRANSITION_DELAY_MS));
    127                 assertEquals("transition should be started because of starting window",
    128                         1 /* APP_TRANSITION_STARTING_WINDOW */, log.getSubtype());
    129                 assertNotNull("log should have starting window delay",
    130                         log.getTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS));
    131                 assertNotNull("log should have windows drawn delay",
    132                         log.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS));
    133             }
    134         }
    135         assertTrue("did not find the app start start log for: "
    136                 + intent.getComponent().flattenToShortString(), found);
    137     }
    138 
    139     @Test
    140     public void testReportedDrawn() throws Exception {
    141         Intent intent = new Intent(mContext, ReportedDrawnActivity.class).setFlags(
    142                 Intent.FLAG_ACTIVITY_NEW_TASK);
    143         mContext.startActivity(intent);
    144         mDevice.wait(Until.hasObject(By.pkg(mContext.getPackageName()).depth(0)), LONG_TIMEOUT_MS);
    145 
    146         String className = intent.getComponent().getClassName();
    147         String packageName = intent.getComponent().getPackageName();
    148 
    149         // Sleep until activity under test has reported drawn (after 500ms)
    150         SystemClock.sleep(1000);
    151         Queue<LogMaker> startLogs = MetricsAsserts.findMatchingLogs(mMetricsReader,
    152                 new LogMaker(APP_TRANSITION_REPORTED_DRAWN));
    153         boolean found = false;
    154         for (LogMaker log : startLogs) {
    155             String actualClassName = (String) log.getTaggedData(
    156                     FIELD_CLASS_NAME);
    157             String actualPackageName = log.getPackageName();
    158             if (className.equals(actualClassName) && packageName.equals(actualPackageName)) {
    159                 found = true;
    160                 assertTrue((long) log.getTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS) > 500L);
    161                 assertEquals((int) log.getTaggedData(APP_TRANSITION_PROCESS_RUNNING), 1);
    162                 assertEquals(TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE, log.getType());
    163             }
    164         }
    165         assertTrue("did not find the app start start log for: "
    166                     + intent.getComponent().flattenToShortString(), found);
    167     }
    168 }
    169