19229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine/* 29229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * Copyright (C) 2012 The Android Open Source Project 39229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * 49229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * Licensed under the Apache License, Version 2.0 (the "License"); 59229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * you may not use this file except in compliance with the License. 69229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * You may obtain a copy of the License at 79229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * 89229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * http://www.apache.org/licenses/LICENSE-2.0 99229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * 109229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * Unless required by applicable law or agreed to in writing, software 119229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * distributed under the License is distributed on an "AS IS" BASIS, 129229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * See the License for the specific language governing permissions and 149229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * limitations under the License. 159229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine */ 169229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavinepackage com.android.tests.memoryusage; 179229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 189229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.app.ActivityManager; 199229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.app.ActivityManager.ProcessErrorStateInfo; 209229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.app.ActivityManager.RunningAppProcessInfo; 21d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavineimport android.app.IActivityManager; 22e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhuimport android.app.UiAutomation; 239229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.content.Context; 249229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.content.Intent; 259229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.content.pm.PackageManager; 269229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.content.pm.PackageManager.NameNotFoundException; 279229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.content.pm.ResolveInfo; 289229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.os.Bundle; 299229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.os.Debug.MemoryInfo; 30d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavineimport android.os.RemoteException; 31d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavineimport android.os.UserHandle; 329229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.test.InstrumentationTestCase; 339229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport android.util.Log; 349229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 359229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport java.util.ArrayList; 369229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport java.util.HashMap; 376c77e104bcb265d29f357b7fb5737153c048bcdbwsmlbyimport java.util.HashSet; 389229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport java.util.List; 399229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavineimport java.util.Map; 406c77e104bcb265d29f357b7fb5737153c048bcdbwsmlbyimport java.util.Set; 419229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 429229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine/** 439229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * This test is intended to measure the amount of memory applications use when 449229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * they start. Names of the applications are passed in command line, and the 459229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * test starts each application, waits until its memory usage is stabilized and 469229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * reports the total PSS in kilobytes of each processes. 479229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * The instrumentation expects the following key to be passed on the command line: 489229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * apps - A list of applications to start and their corresponding result keys 499229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * in the following format: 509229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine * -e apps <app name>^<result key>|<app name>^<result key> 519229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine */ 529229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavinepublic class MemoryUsageTest extends InstrumentationTestCase { 539229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 549229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private static final int SLEEP_TIME = 1000; 559229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private static final int THRESHOLD = 1024; 56d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine private static final int MAX_ITERATIONS = 20; 57d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine private static final int MIN_ITERATIONS = 6; 58d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine private static final int JOIN_TIMEOUT = 10000; 599229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 609229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private static final String TAG = "MemoryUsageInstrumentation"; 619229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private static final String KEY_APPS = "apps"; 626c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby private static final String KEY_PROCS = "persistent"; 636c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby private static final String LAUNCHER_KEY = "launcher"; 642effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine private Map<String, Intent> mNameToIntent; 652effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine private Map<String, String> mNameToProcess; 662effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine private Map<String, String> mNameToResultKey; 676c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby private Set<String> mPersistentProcesses; 68d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine private IActivityManager mAm; 69d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine 70e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu @Override 71e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu protected void setUp() throws Exception { 72e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu super.setUp(); 73e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0); 74e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu } 75e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu 76e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu @Override 77e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu protected void tearDown() throws Exception { 78e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE); 79e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu super.tearDown(); 80e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu } 81e2a03fe43d1f8eb5a6ada046870dcc35392d8f17Guang Zhu 829229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine public void testMemory() { 839229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine MemoryUsageInstrumentation instrumentation = 84d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine (MemoryUsageInstrumentation) getInstrumentation(); 859229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Bundle args = instrumentation.getBundle(); 86dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka mAm = ActivityManager.getService(); 879229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 889229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine createMappings(); 899229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine parseArgs(args); 909229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 919229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Bundle results = new Bundle(); 922effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine for (String app : mNameToResultKey.keySet()) { 936c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby if (!mPersistentProcesses.contains(app)) { 946c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby String processName; 956c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby try { 966c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby processName = startApp(app); 976c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby measureMemory(app, processName, results); 986c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby closeApp(); 996c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby } catch (NameNotFoundException e) { 1006c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby Log.i(TAG, "Application " + app + " not found"); 1016c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby } 1026c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby } else { 1036c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby measureMemory(app, app, results); 1049229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1059229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1069229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine instrumentation.sendStatus(0, results); 1079229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1089229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1096c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby private String getLauncherPackageName() { 1106c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby Intent intent = new Intent(Intent.ACTION_MAIN); 1116c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby intent.addCategory(Intent.CATEGORY_HOME); 1126c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby ResolveInfo resolveInfo = getInstrumentation().getContext(). 1136c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); 1146c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby return resolveInfo.activityInfo.packageName; 1156c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby } 1169229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1176c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby private Map<String, String> parseListToMap(String list) { 1186c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby Map<String, String> map = new HashMap<String, String>(); 1196c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby String names[] = list.split("\\|"); 1206c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby for (String pair : names) { 1219229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine String[] parts = pair.split("\\^"); 1229229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (parts.length != 2) { 1239229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.e(TAG, "The apps key is incorectly formatted"); 1249229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine fail(); 1259229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1266c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby map.put(parts[0], parts[1]); 1276c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby } 1286c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby return map; 1296c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby } 1309229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1316c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby private void parseArgs(Bundle args) { 1326c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby mNameToResultKey = new HashMap<String, String>(); 1336c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby mPersistentProcesses = new HashSet<String>(); 1346c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby String appList = args.getString(KEY_APPS); 1356c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby String procList = args.getString(KEY_PROCS); 1366c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby String mLauncherPackageName = getLauncherPackageName(); 1376c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby mPersistentProcesses.add(mLauncherPackageName); 1386c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby mNameToResultKey.put(mLauncherPackageName, LAUNCHER_KEY); 1396c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby if (appList == null && procList == null) 1406c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby return; 1416c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby if (appList != null) { 1426c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby mNameToResultKey.putAll(parseListToMap(appList)); 1436c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby } 1446c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby if (procList != null) { 1456c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby Map<String, String> procMap = parseListToMap(procList); 1466c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby mPersistentProcesses.addAll(procMap.keySet()); 1476c77e104bcb265d29f357b7fb5737153c048bcdbwsmlby mNameToResultKey.putAll(procMap); 1489229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1499229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1509229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1519229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private void createMappings() { 1522effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine mNameToIntent = new HashMap<String, Intent>(); 1532effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine mNameToProcess = new HashMap<String, String>(); 1549229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1559229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine PackageManager pm = getInstrumentation().getContext() 1569229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine .getPackageManager(); 1579229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 1589229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 1599229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0); 1609229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (ris == null || ris.isEmpty()) { 1619229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.i(TAG, "Could not find any apps"); 1629229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } else { 1639229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine for (ResolveInfo ri : ris) { 1649229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.i(TAG, "Name: " + ri.loadLabel(pm).toString() 1659229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine + " package: " + ri.activityInfo.packageName 1669229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine + " name: " + ri.activityInfo.name); 1679229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Intent startIntent = new Intent(intentToResolve); 1689229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1699229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1709229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine startIntent.setClassName(ri.activityInfo.packageName, 1719229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine ri.activityInfo.name); 1722effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine mNameToIntent.put(ri.loadLabel(pm).toString(), startIntent); 1732effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine mNameToProcess.put(ri.loadLabel(pm).toString(), 1749229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine ri.activityInfo.processName); 1759229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1769229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1779229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1789229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1799229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private String startApp(String appName) throws NameNotFoundException { 1809229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.i(TAG, "Starting " + appName); 1819229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1822effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine if (!mNameToProcess.containsKey(appName)) 1839229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine throw new NameNotFoundException("Could not find: " + appName); 1849229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 1852effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine String process = mNameToProcess.get(appName); 1862effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine Intent startIntent = mNameToIntent.get(appName); 187d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine 188d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent); 189d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine Thread t = new Thread(runnable); 190d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine t.start(); 191d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine try { 192d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine t.join(JOIN_TIMEOUT); 193d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } catch (InterruptedException e) { 194d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine // ignore 195d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } 196d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine 1979229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return process; 1989229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 1999229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 200a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine private void closeApp() { 201a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine Intent homeIntent = new Intent(Intent.ACTION_MAIN); 202a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine homeIntent.addCategory(Intent.CATEGORY_HOME); 203a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 204a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 205a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine getInstrumentation().getContext().startActivity(homeIntent); 206a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine sleep(3000); 207a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine } 208a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine 2099229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private void measureMemory(String appName, String processName, 2109229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Bundle results) { 2119229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine List<Integer> pssData = new ArrayList<Integer>(); 2129229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine int pss = 0; 2139229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine int iteration = 0; 2149229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine while (iteration < MAX_ITERATIONS) { 215a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine sleep(SLEEP_TIME); 2169229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine pss = getPss(processName); 2179229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.i(TAG, appName + "=" + pss); 2189229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (pss < 0) { 2199229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine reportError(appName, processName, results); 2209229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return; 2219229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2229229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine pssData.add(pss); 2239229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (iteration >= MIN_ITERATIONS && stabilized(pssData)) { 2242effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine results.putInt(mNameToResultKey.get(appName), pss); 2259229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return; 2269229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2279229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine iteration++; 2289229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2299229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2309229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.w(TAG, appName + " memory usage did not stabilize"); 2312effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine results.putInt(mNameToResultKey.get(appName), average(pssData)); 2329229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2339229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2349229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private int average(List<Integer> pssData) { 2359229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine int sum = 0; 2369229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine for (int sample : pssData) { 2379229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine sum += sample; 2389229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2399229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2409229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return sum / pssData.size(); 2419229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2429229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2439229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private boolean stabilized(List<Integer> pssData) { 2449229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (pssData.size() < 3) 2459229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return false; 2469229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine int diff1 = Math.abs(pssData.get(pssData.size() - 1) - pssData.get(pssData.size() - 2)); 2479229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine int diff2 = Math.abs(pssData.get(pssData.size() - 2) - pssData.get(pssData.size() - 3)); 2489229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2499229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.i(TAG, "diff1=" + diff1 + " diff2=" + diff2); 2509229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2519229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return (diff1 + diff2) < THRESHOLD; 2529229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2539229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 254a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine private void sleep(int time) { 2559229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine try { 256a9d9decf87a040087a9bda4340d53c21cd3e672aMaxim Siniavine Thread.sleep(time); 2579229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } catch (InterruptedException e) { 2589229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine // ignore 2599229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2609229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2619229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2629229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private void reportError(String appName, String processName, Bundle results) { 2639229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine ActivityManager am = (ActivityManager) getInstrumentation() 2649229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine .getContext().getSystemService(Context.ACTIVITY_SERVICE); 2659229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState(); 2669229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (crashes != null) { 2679229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine for (ProcessErrorStateInfo crash : crashes) { 2689229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (!crash.processName.equals(processName)) 2699229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine continue; 2709229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2719229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.w(TAG, appName + " crashed: " + crash.shortMsg); 2722effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine results.putString(mNameToResultKey.get(appName), crash.shortMsg); 2739229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return; 2749229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2759229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2769229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2772effa64ab7192d9c41cbbe1fd57d61d6d6f94ba8Maxim Siniavine results.putString(mNameToResultKey.get(appName), 2789229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine "Crashed for unknown reason"); 2799229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine Log.w(TAG, appName 2809229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine + " not found in process list, most likely it is crashed"); 2819229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2829229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2839229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine private int getPss(String processName) { 2849229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine ActivityManager am = (ActivityManager) getInstrumentation() 2859229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine .getContext().getSystemService(Context.ACTIVITY_SERVICE); 2869229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine List<RunningAppProcessInfo> apps = am.getRunningAppProcesses(); 2879229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2889229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine for (RunningAppProcessInfo proc : apps) { 2899229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine if (!proc.processName.equals(processName)) { 2909229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine continue; 2919229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 2929229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2939229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine int[] pids = { 294d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine proc.pid }; 2959229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2969229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0]; 2979229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return meminfo.getTotalPss(); 2989229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine 2999229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 3009229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine return -1; 3019229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine } 302d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine 303d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine private class AppLaunchRunnable implements Runnable { 304d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine private Intent mLaunchIntent; 305d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine 306d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine public AppLaunchRunnable(Intent intent) { 307d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine mLaunchIntent = intent; 308d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } 309d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine 310d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine public void run() { 311d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine try { 312d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine String mimeType = mLaunchIntent.getType(); 313d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine if (mimeType == null && mLaunchIntent.getData() != null 314d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine && "content".equals(mLaunchIntent.getData().getScheme())) { 315d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(), 316d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine UserHandle.USER_CURRENT); 317d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } 318d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine 319f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mAm.startActivityAndWait(null, null, mLaunchIntent, mimeType, 3201b012d302b56b4adf950035136d1d191a1936d5aJeff Hao null, null, 0, mLaunchIntent.getFlags(), null, null, 321d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine UserHandle.USER_CURRENT_OR_SELF); 322d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } catch (RemoteException e) { 323d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine Log.w(TAG, "Error launching app", e); 324d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } 325d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } 326d85b8d57a0ce0514a1c9ea8f763b95aa94711645Maxim Siniavine } 3279229700728ec4b7bca28da5325b48a4acb4bfc0dMaxim Siniavine} 328