FileDocCategorySizeDatePackage
MemoryUsageTest.javaAPI DocAndroid 5.1 API12250Thu Mar 12 22:22:44 GMT 2015com.android.tests.memoryusage

MemoryUsageTest

public class MemoryUsageTest extends android.test.InstrumentationTestCase
This test is intended to measure the amount of memory applications use when they start. Names of the applications are passed in command line, and the test starts each application, waits until its memory usage is stabilized and reports the total PSS in kilobytes of each processes. The instrumentation expects the following key to be passed on the command line: apps - A list of applications to start and their corresponding result keys in the following format: -e apps ^|^

Fields Summary
private static final int
SLEEP_TIME
private static final int
THRESHOLD
private static final int
MAX_ITERATIONS
private static final int
MIN_ITERATIONS
private static final int
JOIN_TIMEOUT
private static final String
TAG
private static final String
KEY_APPS
private static final String
KEY_PROCS
private static final String
LAUNCHER_KEY
private Map
mNameToIntent
private Map
mNameToProcess
private Map
mNameToResultKey
private Set
mPersistentProcesses
private android.app.IActivityManager
mAm
Constructors Summary
Methods Summary
private intaverage(java.util.List pssData)

        int sum = 0;
        for (int sample : pssData) {
            sum += sample;
        }

        return sum / pssData.size();
    
private voidcloseApp()

        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        getInstrumentation().getContext().startActivity(homeIntent);
        sleep(3000);
    
private voidcreateMappings()

        mNameToIntent = new HashMap<String, Intent>();
        mNameToProcess = new HashMap<String, String>();

        PackageManager pm = getInstrumentation().getContext()
                .getPackageManager();
        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
        List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
        if (ris == null || ris.isEmpty()) {
            Log.i(TAG, "Could not find any apps");
        } else {
            for (ResolveInfo ri : ris) {
                Log.i(TAG, "Name: " + ri.loadLabel(pm).toString()
                        + " package: " + ri.activityInfo.packageName
                        + " name: " + ri.activityInfo.name);
                Intent startIntent = new Intent(intentToResolve);
                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                startIntent.setClassName(ri.activityInfo.packageName,
                        ri.activityInfo.name);
                mNameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
                mNameToProcess.put(ri.loadLabel(pm).toString(),
                        ri.activityInfo.processName);
            }
        }
    
private java.lang.StringgetLauncherPackageName()

      Intent intent = new Intent(Intent.ACTION_MAIN);
      intent.addCategory(Intent.CATEGORY_HOME);
      ResolveInfo resolveInfo = getInstrumentation().getContext().
          getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
      return resolveInfo.activityInfo.packageName;
    
private intgetPss(java.lang.String processName)

        ActivityManager am = (ActivityManager) getInstrumentation()
                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();

        for (RunningAppProcessInfo proc : apps) {
            if (!proc.processName.equals(processName)) {
                continue;
            }

            int[] pids = {
                    proc.pid };

            MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
            return meminfo.getTotalPss();

        }
        return -1;
    
private voidmeasureMemory(java.lang.String appName, java.lang.String processName, android.os.Bundle results)

        List<Integer> pssData = new ArrayList<Integer>();
        int pss = 0;
        int iteration = 0;
        while (iteration < MAX_ITERATIONS) {
            sleep(SLEEP_TIME);
            pss = getPss(processName);
            Log.i(TAG, appName + "=" + pss);
            if (pss < 0) {
                reportError(appName, processName, results);
                return;
            }
            pssData.add(pss);
            if (iteration >= MIN_ITERATIONS && stabilized(pssData)) {
                results.putInt(mNameToResultKey.get(appName), pss);
                return;
            }
            iteration++;
        }

        Log.w(TAG, appName + " memory usage did not stabilize");
        results.putInt(mNameToResultKey.get(appName), average(pssData));
    
private voidparseArgs(android.os.Bundle args)

        mNameToResultKey = new HashMap<String, String>();
        mPersistentProcesses = new HashSet<String>();
        String appList = args.getString(KEY_APPS);
        String procList = args.getString(KEY_PROCS);
        String mLauncherPackageName = getLauncherPackageName();
        mPersistentProcesses.add(mLauncherPackageName);
        mNameToResultKey.put(mLauncherPackageName, LAUNCHER_KEY);
        if (appList == null && procList == null)
            return;
        if (appList != null) {
            mNameToResultKey.putAll(parseListToMap(appList));
        }
        if (procList != null) {
            Map<String, String> procMap = parseListToMap(procList);
            mPersistentProcesses.addAll(procMap.keySet());
            mNameToResultKey.putAll(procMap);
        }
    
private java.util.MapparseListToMap(java.lang.String list)

        Map<String, String> map = new HashMap<String, String>();
        String names[] = list.split("\\|");
        for (String pair : names) {
            String[] parts = pair.split("\\^");
            if (parts.length != 2) {
                Log.e(TAG, "The apps key is incorectly formatted");
                fail();
            }
            map.put(parts[0], parts[1]);
        }
        return map;
    
private voidreportError(java.lang.String appName, java.lang.String processName, android.os.Bundle results)

        ActivityManager am = (ActivityManager) getInstrumentation()
                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
        if (crashes != null) {
            for (ProcessErrorStateInfo crash : crashes) {
                if (!crash.processName.equals(processName))
                    continue;

                Log.w(TAG, appName + " crashed: " + crash.shortMsg);
                results.putString(mNameToResultKey.get(appName), crash.shortMsg);
                return;
            }
        }

        results.putString(mNameToResultKey.get(appName),
                "Crashed for unknown reason");
        Log.w(TAG, appName
                + " not found in process list, most likely it is crashed");
    
protected voidsetUp()


    
         
        super.setUp();
        getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);
    
private voidsleep(int time)

        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            // ignore
        }
    
private booleanstabilized(java.util.List pssData)

        if (pssData.size() < 3)
            return false;
        int diff1 = Math.abs(pssData.get(pssData.size() - 1) - pssData.get(pssData.size() - 2));
        int diff2 = Math.abs(pssData.get(pssData.size() - 2) - pssData.get(pssData.size() - 3));

        Log.i(TAG, "diff1=" + diff1 + " diff2=" + diff2);

        return (diff1 + diff2) < THRESHOLD;
    
private java.lang.StringstartApp(java.lang.String appName)

        Log.i(TAG, "Starting " + appName);

        if (!mNameToProcess.containsKey(appName))
            throw new NameNotFoundException("Could not find: " + appName);

        String process = mNameToProcess.get(appName);
        Intent startIntent = mNameToIntent.get(appName);

        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
        Thread t = new Thread(runnable);
        t.start();
        try {
            t.join(JOIN_TIMEOUT);
        } catch (InterruptedException e) {
            // ignore
        }

        return process;
    
protected voidtearDown()

        getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
        super.tearDown();
    
public voidtestMemory()

        MemoryUsageInstrumentation instrumentation =
                (MemoryUsageInstrumentation) getInstrumentation();
        Bundle args = instrumentation.getBundle();
        mAm = ActivityManagerNative.getDefault();

        createMappings();
        parseArgs(args);

        Bundle results = new Bundle();
        for (String app : mNameToResultKey.keySet()) {
            if (!mPersistentProcesses.contains(app)) {
                String processName;
                try {
                    processName = startApp(app);
                    measureMemory(app, processName, results);
                    closeApp();
                } catch (NameNotFoundException e) {
                    Log.i(TAG, "Application " + app + " not found");
                }
            } else {
                measureMemory(app, app, results);
            }
        }
        instrumentation.sendStatus(0, results);