AppLaunch.java revision 32abd66ebd6d63cfc631ce5f4425bb5dc4a4beac
1f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine/*
232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu * Copyright (C) 2013 The Android Open Source Project
3f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine *
4f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Licensed under the Apache License, Version 2.0 (the "License");
5f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * you may not use this file except in compliance with the License.
6f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * You may obtain a copy of the License at
7f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine *
8f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine *      http://www.apache.org/licenses/LICENSE-2.0
9f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine *
10f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Unless required by applicable law or agreed to in writing, software
11f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * distributed under the License is distributed on an "AS IS" BASIS,
12f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * See the License for the specific language governing permissions and
14f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * limitations under the License.
15f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine */
16f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavinepackage com.android.tests.applaunch;
17f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
18f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManager;
19f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManager.ProcessErrorStateInfo;
20f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.ActivityManagerNative;
21f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.app.IActivityManager;
2213f77349778fbe95d665542be6f05006879854e2Guang Zhuimport android.app.IActivityManager.WaitResult;
23f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.Context;
24f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.Intent;
25f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.PackageManager;
26f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.PackageManager.NameNotFoundException;
27f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.content.pm.ResolveInfo;
28f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.Bundle;
29f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.RemoteException;
30f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.os.UserHandle;
31f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestCase;
32f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.test.InstrumentationTestRunner;
33f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport android.util.Log;
34f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
3532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhuimport java.util.HashMap;
36c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhuimport java.util.LinkedHashMap;
37f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.List;
38f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavineimport java.util.Map;
39f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
40f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine/**
41f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * This test is intended to measure the time it takes for the apps to start.
42f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * Names of the applications are passed in command line, and the
43f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * test starts each application, and reports the start up time in milliseconds.
44f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * The instrumentation expects the following key to be passed on the command line:
45f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * apps - A list of applications to start and their corresponding result keys
46f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * in the following format:
47f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine * -e apps <app name>^<result key>|<app name>^<result key>
48f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine */
49f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavinepublic class AppLaunch extends InstrumentationTestCase {
50f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
51f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private static final int JOIN_TIMEOUT = 10000;
5232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private static final String TAG = AppLaunch.class.getSimpleName();
53f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private static final String KEY_APPS = "apps";
5432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
5532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 7500; //7.5s to allow app to idle
5632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
5732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps
58f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
59f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private Map<String, Intent> mNameToIntent;
60f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private Map<String, String> mNameToProcess;
61f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private Map<String, String> mNameToResultKey;
6232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private Map<String, Long> mNameToLaunchTime;
63f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private IActivityManager mAm;
6432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private int mLaunchIterations = 10;
6532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private Bundle mResult = new Bundle();
66f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
6732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException {
68f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        InstrumentationTestRunner instrumentation =
69f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                (InstrumentationTestRunner)getInstrumentation();
703a34d17412a5a304e39be1966a16627677d2136fSvetoslav        Bundle args = instrumentation.getArguments();
71f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        mAm = ActivityManagerNative.getDefault();
72f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
73f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        createMappings();
74f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        parseArgs(args);
75f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
7632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        // do initial app launch, without force stopping
77f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        for (String app : mNameToResultKey.keySet()) {
7832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            long launchTime = startApp(app, false);
7932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            if (launchTime <=0 ) {
8032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                mNameToLaunchTime.put(app, -1L);
8132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                // simply pass the app if launch isn't successful
8232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                // error should have already been logged by startApp
8332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                continue;
8432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            }
8532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
8632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            closeApp(app, false);
8732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
8832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        }
8932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        // do the real app launch now
9032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        for (int i = 0; i < mLaunchIterations; i++) {
9132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            for (String app : mNameToResultKey.keySet()) {
9232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                long totalLaunchTime = mNameToLaunchTime.get(app);
9332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                long launchTime = 0;
9432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                if (totalLaunchTime < 0) {
9532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    // skip if the app has previous failures
9632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    continue;
9732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                }
9832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                launchTime = startApp(app, true);
9932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                if (launchTime <= 0) {
10032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    // if it fails once, skip the rest of the launches
10132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    mNameToLaunchTime.put(app, -1L);
10232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    continue;
10332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                }
10432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                totalLaunchTime += launchTime;
10532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                mNameToLaunchTime.put(app, totalLaunchTime);
10632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                sleep(POST_LAUNCH_IDLE_TIMEOUT);
10732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                closeApp(app, true);
10832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
10932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            }
11032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        }
11132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        for (String app : mNameToResultKey.keySet()) {
11232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            long totalLaunchTime = mNameToLaunchTime.get(app);
11332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            if (totalLaunchTime != -1) {
11432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                mResult.putDouble(mNameToResultKey.get(app),
11532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                        ((double) totalLaunchTime) / mLaunchIterations);
116f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            }
117f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
11832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        instrumentation.sendStatus(0, mResult);
119f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
120f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
121f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private void parseArgs(Bundle args) {
122c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu        mNameToResultKey = new LinkedHashMap<String, String>();
12332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        mNameToLaunchTime = new HashMap<String, Long>();
12432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS);
12532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        if (launchIterations != null) {
12632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            mLaunchIterations = Integer.parseInt(launchIterations);
12732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        }
128f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        String appList = args.getString(KEY_APPS);
129f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        if (appList == null)
130f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            return;
131f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
132f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        String appNames[] = appList.split("\\|");
133f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        for (String pair : appNames) {
134f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            String[] parts = pair.split("\\^");
135f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            if (parts.length != 2) {
136f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                Log.e(TAG, "The apps key is incorectly formatted");
137f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                fail();
138f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            }
139f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
140f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            mNameToResultKey.put(parts[0], parts[1]);
14132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            mNameToLaunchTime.put(parts[0], 0L);
142f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
143f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
144f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
145f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private void createMappings() {
146c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu        mNameToIntent = new LinkedHashMap<String, Intent>();
147c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu        mNameToProcess = new LinkedHashMap<String, String>();
148f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
149f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        PackageManager pm = getInstrumentation().getContext()
150f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                .getPackageManager();
151f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
152f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
153f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
154f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        if (ris == null || ris.isEmpty()) {
155f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            Log.i(TAG, "Could not find any apps");
156f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        } else {
157f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            for (ResolveInfo ri : ris) {
158f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                Intent startIntent = new Intent(intentToResolve);
159f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
160f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
161f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                startIntent.setClassName(ri.activityInfo.packageName,
162f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                        ri.activityInfo.name);
16332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                String appName = ri.loadLabel(pm).toString();
16432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                if (appName != null) {
16532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    mNameToIntent.put(appName, startIntent);
16632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    mNameToProcess.put(appName, ri.activityInfo.processName);
16732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                }
168f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            }
169f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
170f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
171f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
17232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private long startApp(String appName, boolean forceStopBeforeLaunch)
173f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            throws NameNotFoundException, RemoteException {
174f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        Log.i(TAG, "Starting " + appName);
175f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
176f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        Intent startIntent = mNameToIntent.get(appName);
177c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu        if (startIntent == null) {
178c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu            Log.w(TAG, "App does not exist: " + appName);
17932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            mResult.putString(mNameToResultKey.get(appName), "App does not exist");
18032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            return -1;
181c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu        }
18232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch);
183f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        Thread t = new Thread(runnable);
184f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        t.start();
185f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        try {
186f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            t.join(JOIN_TIMEOUT);
187f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        } catch (InterruptedException e) {
188f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            // ignore
189f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
190c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu        WaitResult result = runnable.getResult();
19132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        // report error if any of the following is true:
19232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        // * launch thread is alive
19332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        // * result is not null, but:
19432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        //   * result is not START_SUCESS
19532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        //   * or in case of no force stop, result is not TASK_TO_FRONT either
19632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        if (t.isAlive() || (result != null
19732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                && ((result.result != ActivityManager.START_SUCCESS)
19832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                        && (!forceStopBeforeLaunch
19932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                                && result.result != ActivityManager.START_TASK_TO_FRONT)))) {
200f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            Log.w(TAG, "Assuming app " + appName + " crashed.");
20132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            reportError(appName, mNameToProcess.get(appName));
20232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            return -1;
203f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
20432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        return result.thisTime;
205f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
206f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
20732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private void closeApp(String appName, boolean forceStopApp) {
208f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
209f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        homeIntent.addCategory(Intent.CATEGORY_HOME);
210f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
211f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
212f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        getInstrumentation().getContext().startActivity(homeIntent);
21332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        sleep(POST_LAUNCH_IDLE_TIMEOUT);
21432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        if (forceStopApp) {
21532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            Intent startIntent = mNameToIntent.get(appName);
21632abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            if (startIntent != null) {
21732abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                String packageName = startIntent.getComponent().getPackageName();
21832abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                try {
21932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
22032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                } catch (RemoteException e) {
22132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    Log.w(TAG, "Error closing app", e);
22232abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                }
22313f77349778fbe95d665542be6f05006879854e2Guang Zhu            }
22413f77349778fbe95d665542be6f05006879854e2Guang Zhu        }
225f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
226f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
227f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private void sleep(int time) {
228f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        try {
229f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            Thread.sleep(time);
230f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        } catch (InterruptedException e) {
231f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            // ignore
232f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
233f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
234f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
23532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu    private void reportError(String appName, String processName) {
236f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        ActivityManager am = (ActivityManager) getInstrumentation()
237f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
238f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
239f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        if (crashes != null) {
240f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            for (ProcessErrorStateInfo crash : crashes) {
241f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                if (!crash.processName.equals(processName))
242f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                    continue;
243f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
244f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                Log.w(TAG, appName + " crashed: " + crash.shortMsg);
24532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                mResult.putString(mNameToResultKey.get(appName), crash.shortMsg);
246f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                return;
247f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            }
248f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
249f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
25032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        mResult.putString(mNameToResultKey.get(appName),
251f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                "Crashed for unknown reason");
252f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        Log.w(TAG, appName
253f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                + " not found in process list, most likely it is crashed");
254f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
255f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
256f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    private class AppLaunchRunnable implements Runnable {
257f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        private Intent mLaunchIntent;
258f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        private IActivityManager.WaitResult mResult;
25932abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        private boolean mForceStopBeforeLaunch;
26032abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu
26132abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu        public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch) {
262f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            mLaunchIntent = intent;
26332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu            mForceStopBeforeLaunch = forceStopBeforeLaunch;
264f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
265f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
266f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        public IActivityManager.WaitResult getResult() {
267f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            return mResult;
268f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
269f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
270f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        public void run() {
271f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            try {
272c28a062ffd7edbdbd936c750fa3ec3f81b0d1b44Guang Zhu                String packageName = mLaunchIntent.getComponent().getPackageName();
27332abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                if (mForceStopBeforeLaunch) {
27432abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                    mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
27532abd66ebd6d63cfc631ce5f4425bb5dc4a4beacGuang Zhu                }
276f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                String mimeType = mLaunchIntent.getType();
277f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                if (mimeType == null && mLaunchIntent.getData() != null
278f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                        && "content".equals(mLaunchIntent.getData().getScheme())) {
279f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                    mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
280f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                            UserHandle.USER_CURRENT);
281f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                }
282f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine
283f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                mResult = mAm.startActivityAndWait(null, null, mLaunchIntent, mimeType,
284f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                        null, null, 0, mLaunchIntent.getFlags(), null, null, null,
285f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                        UserHandle.USER_CURRENT);
286f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            } catch (RemoteException e) {
287f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine                Log.w(TAG, "Error launching app", e);
288f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine            }
289f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine        }
290f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine    }
291f58e5b6cdcecee6184784b3a6ac33f60341de170Maxim Siniavine}
292