1 /* 2 * Copyright (C) 2020 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 com.android.settings.tests.perf; 17 18 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 19 20 import static junit.framework.TestCase.fail; 21 22 import android.app.Instrumentation; 23 import android.os.Bundle; 24 import android.util.Log; 25 import android.support.test.uiautomator.By; 26 import android.support.test.uiautomator.UiDevice; 27 import android.support.test.uiautomator.UiSelector; 28 import android.support.test.uiautomator.Until; 29 30 import androidx.test.InstrumentationRegistry; 31 import androidx.test.runner.AndroidJUnit4; 32 33 import org.junit.After; 34 import org.junit.Before; 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 38 import java.util.ArrayList; 39 import java.util.LinkedHashMap; 40 import java.util.Map; 41 import java.util.Collections; 42 import java.util.regex.Matcher; 43 import java.util.regex.Pattern; 44 45 @RunWith(AndroidJUnit4.class) 46 public class LaunchSettingsTest { 47 private static class Page { 48 String action; 49 String displayName; 50 String title; 51 Page(String action, String displayName, String title)52 Page(String action, String displayName, String title) { 53 this.action = action; 54 this.displayName = displayName; 55 this.title = title; 56 } 57 } 58 59 private static final String SCREEN_TIME_OUT = "7200000"; 60 private static final String DEFAULT_SCREEN_TIMEOUT = "15000"; 61 private static final int TIME_OUT = 5000; 62 private static final int TEST_TIME = 10; 63 private static final Pattern PATTERN = Pattern.compile("TotalTime:\\s[0-9]*"); 64 private static final Page[] PAGES; 65 private static final String TAG = "SettingsPerfTests"; 66 67 static { 68 PAGES = new Page[]{ 69 new Page("android.settings.SETTINGS", "Search settings", "Settings"), 70 new Page("android.settings.WIFI_SETTINGS", "Use Wi‑Fi", "Wi-Fi"), 71 new Page("android.settings.BLUETOOTH_SETTINGS", "Connected devices", "BlueTooth"), 72 new Page("android.settings.APPLICATION_SETTINGS", "App info", "Application"), 73 new Page("android.intent.action.POWER_USAGE_SUMMARY", "Battery", "Battery"), 74 new Page("android.settings.INTERNAL_STORAGE_SETTINGS", "Storage", "Storage") 75 }; 76 } 77 78 private Bundle mBundle; 79 private UiDevice mDevice; 80 private Instrumentation mInstrumentation; 81 private Map<String, ArrayList<Integer>> mResult; 82 private String mDefaultScreenTimeout; 83 private String mDefaultAirplaneModeStatus; 84 85 @Before setUp()86 public void setUp() throws Exception { 87 mBundle = new Bundle(); 88 mDevice = UiDevice.getInstance(getInstrumentation()); 89 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 90 mResult = new LinkedHashMap<>(); 91 mDefaultScreenTimeout = mDevice.executeShellCommand( 92 "settings get system screen_off_timeout"); 93 mDefaultAirplaneModeStatus = getAirplaneModeStatus(); 94 setScreenTimeOut(SCREEN_TIME_OUT); 95 setAirplaneMode(); 96 mDevice.pressHome(); 97 mDevice.waitForIdle(TIME_OUT); 98 99 for (Page page : PAGES) { 100 mResult.put(page.title, new ArrayList<Integer>()); 101 } 102 } 103 104 @After tearDown()105 public void tearDown() throws Exception { 106 putResultToBundle(); 107 mInstrumentation.sendStatus(0, mBundle); 108 resetScreenTimeout(); 109 resetAirplaneMode(); 110 closeApp(); 111 } 112 113 @Test settingsPerformanceTest()114 public void settingsPerformanceTest() throws Exception { 115 for (int i = 0; i < TEST_TIME; i++) { 116 for (Page page : PAGES) { 117 executePreformanceTest(page.action, page.displayName, page.title); 118 } 119 } 120 } 121 executePreformanceTest(String action, String displayName, String title)122 private void executePreformanceTest(String action, String displayName, String title) 123 throws Exception { 124 closeApp(); 125 mDevice.waitForIdle(TIME_OUT); 126 final String mString = mDevice.executeShellCommand("am start -W -a" + action); 127 mDevice.wait(Until.findObject(By.text(displayName)), TIME_OUT); 128 handleLaunchResult(title, mString); 129 } 130 handleLaunchResult(String title, String shellCommandResult)131 private void handleLaunchResult(String title, String shellCommandResult) { 132 Matcher mMatcher = PATTERN.matcher(shellCommandResult); 133 if (mMatcher.find()) { 134 mResult.get(title).add(Integer.valueOf(mMatcher.group().split("\\s")[1])); 135 } else { 136 fail(String.format("Not found %s.\n %s", title, shellCommandResult)); 137 } 138 } 139 closeApp()140 private void closeApp() throws Exception { 141 mDevice.executeShellCommand("am force-stop com.android.settings"); 142 Thread.sleep(1000); 143 } 144 putResultToBundle()145 private void putResultToBundle() { 146 for (String string : mResult.keySet()) { 147 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "max"), 148 getMax(string)); 149 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "min"), 150 getMin(string)); 151 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "avg"), 152 getAvg(string)); 153 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "25 Percentile"), 154 getPercentile(string, 25)); 155 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "50 Percentile"), 156 getPercentile(string, 50)); 157 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "75 Percentile"), 158 getPercentile(string, 75)); 159 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "all_results"), 160 mResult.get(string).toString()); 161 mBundle.putString(String.format("LaunchSettingsTest_%s_%s", string, "results_count"), 162 String.valueOf(mResult.get(string).size())); 163 } 164 } 165 getMax(String page)166 private String getMax(String page) { 167 if (mResult.get(page).size() == TEST_TIME) { 168 return String.format("%s", Collections.max(mResult.get(page))); 169 } 170 Log.e(TAG, String.format("Fail to get max of %s.", page)); 171 return "0"; 172 173 } 174 getMin(String page)175 private String getMin(String page) { 176 if (mResult.get(page).size() == TEST_TIME) { 177 return String.format("%s", Collections.min(mResult.get(page))); 178 } 179 Log.e(TAG, String.format("Fail to get min of %s.", page)); 180 return "0"; 181 } 182 getAvg(String page)183 private String getAvg(String page) { 184 if (mResult.get(page).size() == TEST_TIME) { 185 return String.valueOf((int) mResult.get(page).stream().mapToInt( 186 i -> i).average().orElse(0)); 187 } 188 Log.e(TAG, String.format("Fail to get avg of %s.", page)); 189 return "0"; 190 } 191 setScreenTimeOut(String timeout)192 private void setScreenTimeOut(String timeout) throws Exception { 193 mDevice.executeShellCommand("settings put system screen_off_timeout " + timeout); 194 } 195 resetScreenTimeout()196 private void resetScreenTimeout() throws Exception { 197 String timeout = DEFAULT_SCREEN_TIMEOUT; 198 if (!mDefaultScreenTimeout.isEmpty()) { 199 timeout = mDefaultScreenTimeout; 200 } 201 setScreenTimeOut(timeout); 202 } 203 setAirplaneMode()204 private void setAirplaneMode() throws Exception { 205 if (mDefaultAirplaneModeStatus.equals("0\n")) { 206 clickAirplaneMode(); 207 } 208 } 209 resetAirplaneMode()210 private void resetAirplaneMode() throws Exception { 211 if (!getAirplaneModeStatus().equals(mDefaultAirplaneModeStatus)) { 212 clickAirplaneMode(); 213 } 214 } 215 clickAirplaneMode()216 private void clickAirplaneMode() throws Exception { 217 mDevice.executeShellCommand("am start -W -a android.settings.AIRPLANE_MODE_SETTINGS"); 218 mDevice.waitForIdle(TIME_OUT); 219 mDevice.findObject(By.textContains("Airplane")).click(); 220 mDevice.waitForIdle(TIME_OUT); 221 } 222 getAirplaneModeStatus()223 private String getAirplaneModeStatus() throws Exception { 224 return mDevice.executeShellCommand("settings get global airplane_mode_on"); 225 } 226 getPercentile(String page, double position)227 private String getPercentile(String page, double position) { 228 Collections.sort(mResult.get(page)); 229 if (mResult.get(page).size() == TEST_TIME) { 230 return String.valueOf( 231 mResult.get(page).get((int) (Math.ceil(TEST_TIME * position / 100)) - 1)); 232 } 233 Log.e(TAG, String.format("Fail to get percentile of %s.", page)); 234 return "0"; 235 } 236 }