/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerGlobal;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.PerformanceCollector;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.TestLooperManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AndroidRuntimeException;
import android.util.Log;
import android.view.Display;
import android.view.IWindowManager;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManagerGlobal;

import com.android.internal.content.ReferrerIntent;

import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.concurrent.TimeoutException;

/**
 * Base class for implementing application instrumentation code.  When running
 * with instrumentation turned on, this class will be instantiated for you
 * before any of the application code, allowing you to monitor all of the
 * interaction the system has with the application.  An Instrumentation
 * implementation is described to the system through an AndroidManifest.xml's
 * &lt;instrumentation&gt; tag.
 */
public class Instrumentation {

    /**
     * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 
     * identifies the class that is writing the report.  This can be used to provide more structured
     * logging or reporting capabilities in the IInstrumentationWatcher.
     */
    public static final String REPORT_KEY_IDENTIFIER = "id";
    /**
     * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 
     * identifies a string which can simply be printed to the output stream.  Using these streams
     * provides a "pretty printer" version of the status & final packets.  Any bundles including 
     * this key should also include the complete set of raw key/value pairs, so that the
     * instrumentation can also be launched, and results collected, by an automated system.
     */
    public static final String REPORT_KEY_STREAMRESULT = "stream";

    private static final String TAG = "Instrumentation";

    private static final long CONNECT_TIMEOUT_MILLIS = 60_000;

    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);

    // If set, will print the stack trace for activity starts within the process
    static final boolean DEBUG_START_ACTIVITY = Build.IS_DEBUGGABLE &&
            SystemProperties.getBoolean("persist.wm.debug.start_activity", false);

    /**
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES,
            UiAutomation.FLAG_DONT_USE_ACCESSIBILITY})
    public @interface UiAutomationFlags {};


    private final Object mSync = new Object();
    private ActivityThread mThread = null;
    private MessageQueue mMessageQueue = null;
    private Context mInstrContext;
    private Context mAppContext;
    private ComponentName mComponent;
    private Thread mRunner;
    private List<ActivityWaiter> mWaitingActivities;
    private List<ActivityMonitor> mActivityMonitors;
    private IInstrumentationWatcher mWatcher;
    private IUiAutomationConnection mUiAutomationConnection;
    private boolean mAutomaticPerformanceSnapshots = false;
    private PerformanceCollector mPerformanceCollector;
    private Bundle mPerfMetrics = new Bundle();
    private UiAutomation mUiAutomation;
    private final Object mAnimationCompleteLock = new Object();

    public Instrumentation() {
    }

    /**
     * Called for methods that shouldn't be called by standard apps and
     * should only be used in instrumentation environments. This is not
     * security feature as these classes will still be accessible through
     * reflection, but it will serve as noticeable discouragement from
     * doing such a thing.
     */
    private void checkInstrumenting(String method) {
        // Check if we have an instrumentation context, as init should only get called by
        // the system in startup processes that are being instrumented.
        if (mInstrContext == null) {
            throw new RuntimeException(method +
                    " cannot be called outside of instrumented processes");
        }
    }

    /**
     * Returns if it is being called in an instrumentation environment.
     *
     * @hide
     */
    public boolean isInstrumenting() {
        // Check if we have an instrumentation context, as init should only get called by
        // the system in startup processes that are being instrumented.
        if (mInstrContext == null) {
            return false;
        }
        return true;
    }

    /**
     * Called when the instrumentation is starting, before any application code
     * has been loaded.  Usually this will be implemented to simply call
     * {@link #start} to begin the instrumentation thread, which will then
     * continue execution in {@link #onStart}.
     * 
     * <p>If you do not need your own thread -- that is you are writing your
     * instrumentation to be completely asynchronous (returning to the event
     * loop so that the application can run), you can simply begin your
     * instrumentation here, for example call {@link Context#startActivity} to
     * begin the appropriate first activity of the application. 
     *  
     * @param arguments Any additional arguments that were supplied when the 
     *                  instrumentation was started.
     */
    public void onCreate(Bundle arguments) {
    }

    /**
     * Create and start a new thread in which to run instrumentation.  This new
     * thread will call to {@link #onStart} where you can implement the
     * instrumentation.
     */
    public void start() {
        if (mRunner != null) {
            throw new RuntimeException("Instrumentation already started");
        }
        mRunner = new InstrumentationThread("Instr: " + getClass().getName());
        mRunner.start();
    }

    /**
     * Method where the instrumentation thread enters execution.  This allows
     * you to run your instrumentation code in a separate thread than the
     * application, so that it can perform blocking operation such as
     * {@link #sendKeySync} or {@link #startActivitySync}.
     * 
     * <p>You will typically want to call finish() when this function is done,
     * to end your instrumentation.
     */
    public void onStart() {
    }

    /**
     * This is called whenever the system captures an unhandled exception that
     * was thrown by the application.  The default implementation simply
     * returns false, allowing normal system handling of the exception to take
     * place.
     * 
     * @param obj The client object that generated the exception.  May be an
     *            Application, Activity, BroadcastReceiver, Service, or null.
     * @param e The exception that was thrown.
     *  
     * @return To allow normal system exception process to occur, return false.
     *         If true is returned, the system will proceed as if the exception
     *         didn't happen.
     */
    public boolean onException(Object obj, Throwable e) {
        return false;
    }

    /**
     * Provide a status report about the application.
     *  
     * @param resultCode Current success/failure of instrumentation. 
     * @param results Any results to send back to the code that started the instrumentation.
     */
    public void sendStatus(int resultCode, Bundle results) {
        if (mWatcher != null) {
            try {
                mWatcher.instrumentationStatus(mComponent, resultCode, results);
            }
            catch (RemoteException e) {
                mWatcher = null;
            }
        }
    }

    /**
     * Report some results in the middle of instrumentation execution.  Later results (including
     * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
     */
    public void addResults(Bundle results) {
        IActivityManager am = ActivityManager.getService();
        try {
            am.addInstrumentationResults(mThread.getApplicationThread(), results);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    /**
     * Terminate instrumentation of the application.  This will cause the
     * application process to exit, removing this instrumentation from the next
     * time the application is started.  If multiple processes are currently running
     * for this instrumentation, all of those processes will be killed.
     *  
     * @param resultCode Overall success/failure of instrumentation. 
     * @param results Any results to send back to the code that started the 
     *                instrumentation.
     */
    public void finish(int resultCode, Bundle results) {
        if (mAutomaticPerformanceSnapshots) {
            endPerformanceSnapshot();
        }
        if (mPerfMetrics != null) {
            if (results == null) {
                results = new Bundle();
            }
            results.putAll(mPerfMetrics);
        }
        if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
            mUiAutomation.disconnect();
            mUiAutomation = null;
        }
        mThread.finishInstrumentation(resultCode, results);
    }
    
    public void setAutomaticPerformanceSnapshots() {
        mAutomaticPerformanceSnapshots = true;
        mPerformanceCollector = new PerformanceCollector();
    }

    public void startPerformanceSnapshot() {
        if (!isProfiling()) {
            mPerformanceCollector.beginSnapshot(null);
        }
    }
    
    public void endPerformanceSnapshot() {
        if (!isProfiling()) {
            mPerfMetrics = mPerformanceCollector.endSnapshot();
        }
    }
    
    /**
     * Called when the instrumented application is stopping, after all of the
     * normal application cleanup has occurred.
     */
    public void onDestroy() {
    }

    /**
     * Return the Context of this instrumentation's package.  Note that this is
     * often different than the Context of the application being
     * instrumentated, since the instrumentation code often lives is a
     * different package than that of the application it is running against.
     * See {@link #getTargetContext} to retrieve a Context for the target
     * application.
     * 
     * @return The instrumentation's package context.
     * 
     * @see #getTargetContext
     */
    public Context getContext() {
        return mInstrContext;
    }

    /**
     * Returns complete component name of this instrumentation.
     * 
     * @return Returns the complete component name for this instrumentation.
     */
    public ComponentName getComponentName() {
        return mComponent;
    }
    
    /**
     * Return a Context for the target application being instrumented.  Note
     * that this is often different than the Context of the instrumentation
     * code, since the instrumentation code often lives is a different package
     * than that of the application it is running against. See
     * {@link #getContext} to retrieve a Context for the instrumentation code.
     * 
     * @return A Context in the target application.
     * 
     * @see #getContext
     */
    public Context getTargetContext() {
        return mAppContext;
    }

    /**
     * Return the name of the process this instrumentation is running in.  Note this should
     * only be used for testing and debugging.  If you are thinking about using this to,
     * for example, conditionalize what is initialized in an Application class, it is strongly
     * recommended to instead use lazy initialization (such as a getter for the state that
     * only creates it when requested).  This can greatly reduce the work your process does
     * when created for secondary things, such as to receive a broadcast.
     */
    public String getProcessName() {
        return mThread.getProcessName();
    }

    /**
     * Check whether this instrumentation was started with profiling enabled.
     * 
     * @return Returns true if profiling was enabled when starting, else false.
     */
    public boolean isProfiling() {
        return mThread.isProfiling();
    }

    /**
     * This method will start profiling if isProfiling() returns true. You should
     * only call this method if you set the handleProfiling attribute in the 
     * manifest file for this Instrumentation to true.  
     */
    public void startProfiling() {
        if (mThread.isProfiling()) {
            File file = new File(mThread.getProfileFilePath());
            file.getParentFile().mkdirs();
            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
        }
    }

    /**
     * Stops profiling if isProfiling() returns true.
     */
    public void stopProfiling() {
        if (mThread.isProfiling()) {
            Debug.stopMethodTracing();
        }
    }

    /**
     * Force the global system in or out of touch mode. This can be used if your
     * instrumentation relies on the UI being in one more or the other when it starts.
     *
     * <p><b>Note:</b> Starting from Android {@link Build.VERSION_CODES#TIRAMISU}, this method
     * will only take effect if the instrumentation was sourced from a process with
     * {@code MODIFY_TOUCH_MODE_STATE} internal permission granted (shell already have it).
     *
     * @param inTouch Set to true to be in touch mode, false to be in focus mode.
     */
    public void setInTouchMode(boolean inTouch) {
        try {
            IWindowManager.Stub.asInterface(
                    ServiceManager.getService("window")).setInTouchModeOnAllDisplays(inTouch);
        } catch (RemoteException e) {
            // Shouldn't happen!
        }
    }

    /**
     * Resets the {@link #setInTouchMode touch mode} to the device default.
     */
    public void resetInTouchMode() {
        final boolean defaultInTouchMode = getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_defaultInTouchMode);
        setInTouchMode(defaultInTouchMode);
    }

    /**
     * Schedule a callback for when the application's main thread goes idle
     * (has no more events to process).
     *
     * @param recipient Called the next time the thread's message queue is
     *                  idle.
     */
    public void waitForIdle(Runnable recipient) {
        mMessageQueue.addIdleHandler(new Idler(recipient));
        mThread.getHandler().post(new EmptyRunnable());
    }

    /**
     * Synchronously wait for the application to be idle.  Can not be called
     * from the main application thread -- use {@link #start} to execute
     * instrumentation in its own thread.
     */
    public void waitForIdleSync() {
        validateNotAppThread();
        Idler idler = new Idler(null);
        mMessageQueue.addIdleHandler(idler);
        mThread.getHandler().post(new EmptyRunnable());
        idler.waitForIdle();
    }

    private void waitForEnterAnimationComplete(Activity activity) {
        synchronized (mAnimationCompleteLock) {
            long timeout = 5000;
            try {
                // We need to check that this specified Activity completed the animation, not just
                // any Activity. If it was another Activity, then decrease the timeout by how long
                // it's already waited and wait for the thread to wakeup again.
                while (timeout > 0 && !activity.mEnterAnimationComplete) {
                    long startTime = System.currentTimeMillis();
                    mAnimationCompleteLock.wait(timeout);
                    long totalTime = System.currentTimeMillis() - startTime;
                    timeout -= totalTime;
                }
            } catch (InterruptedException e) {
            }
        }
    }

    /** @hide */
    public void onEnterAnimationComplete() {
        synchronized (mAnimationCompleteLock) {
            mAnimationCompleteLock.notifyAll();
        }
    }

    /**
     * Execute a call on the application's main thread, blocking until it is
     * complete.  Useful for doing things that are not thread-safe, such as
     * looking at or modifying the view hierarchy.
     * 
     * @param runner The code to run on the main thread.
     */
    public void runOnMainSync(Runnable runner) {
        validateNotAppThread();
        SyncRunnable sr = new SyncRunnable(runner);
        mThread.getHandler().post(sr);
        sr.waitForComplete();
    }

    boolean isSdkSandboxAllowedToStartActivities() {
        return Process.isSdkSandbox()
                && mThread != null
                && mThread.mBoundApplication != null
                && mThread.mBoundApplication.isSdkInSandbox
                && getContext() != null
                && (getContext()
                                .checkSelfPermission(
                                        android.Manifest.permission
                                                .START_ACTIVITIES_FROM_SDK_SANDBOX)
                        == PackageManager.PERMISSION_GRANTED);
    }

    /**
     * Activity name resolution for CTS-in-SdkSandbox tests requires some adjustments. Intents
     * generated using {@link Context#getPackageName()} use the SDK sandbox package name in the
     * component field instead of the test package name. An SDK-in-sandbox test attempting to launch
     * an activity in the test package will encounter name resolution errors when resolving the
     * activity name in the SDK sandbox package.
     *
     * <p>This function replaces the package name of the input intent component to allow activities
     * belonging to a CTS-in-sandbox test to resolve correctly.
     *
     * @param intent the intent to modify to allow CTS-in-sandbox activity resolution.
     */
    private void adjustIntentForCtsInSdkSandboxInstrumentation(@NonNull Intent intent) {
        if (mComponent != null
                && intent.getComponent() != null
                && getContext()
                        .getPackageManager()
                        .getSdkSandboxPackageName()
                        .equals(intent.getComponent().getPackageName())) {
            // Resolve the intent target for the test package, not for the sandbox package.
            intent.setComponent(
                    new ComponentName(
                            mComponent.getPackageName(), intent.getComponent().getClassName()));
        }
        // We match the intent identifier against the running instrumentations for the sandbox.
        intent.setIdentifier(mComponent.getPackageName());
    }

    private ActivityInfo resolveActivityInfoForCtsInSandbox(@NonNull Intent intent) {
        adjustIntentForCtsInSdkSandboxInstrumentation(intent);
        ActivityInfo ai = intent.resolveActivityInfo(getTargetContext().getPackageManager(), 0);
        if (ai != null) {
            ai.processName = mThread.getProcessName();
        }
        return ai;
    }

    /**
     * Start a new activity and wait for it to begin running before returning.
     * In addition to being synchronous, this method as some semantic
     * differences from the standard {@link Context#startActivity} call: the
     * activity component is resolved before talking with the activity manager
     * (its class name is specified in the Intent that this method ultimately
     * starts), and it does not allow you to start activities that run in a
     * different process.  In addition, if the given Intent resolves to
     * multiple activities, instead of displaying a dialog for the user to
     * select an activity, an exception will be thrown.
     *
     * <p>The function returns as soon as the activity goes idle following the
     * call to its {@link Activity#onCreate}.  Generally this means it has gone
     * through the full initialization including {@link Activity#onResume} and
     * drawn and displayed its initial window.
     *
     * @param intent Description of the activity to start.
     *
     * @see Context#startActivity
     * @see #startActivitySync(Intent, Bundle)
     */
    public Activity startActivitySync(Intent intent) {
        return startActivitySync(intent, null /* options */);
    }

    /**
     * Start a new activity and wait for it to begin running before returning.
     * In addition to being synchronous, this method as some semantic
     * differences from the standard {@link Context#startActivity} call: the
     * activity component is resolved before talking with the activity manager
     * (its class name is specified in the Intent that this method ultimately
     * starts), and it does not allow you to start activities that run in a
     * different process.  In addition, if the given Intent resolves to
     * multiple activities, instead of displaying a dialog for the user to
     * select an activity, an exception will be thrown.
     *
     * <p>The function returns as soon as the activity goes idle following the
     * call to its {@link Activity#onCreate}.  Generally this means it has gone
     * through the full initialization including {@link Activity#onResume} and
     * drawn and displayed its initial window.
     *
     * @param intent Description of the activity to start.
     * @param options Additional options for how the Activity should be started.
     * May be null if there are no options.  See {@link android.app.ActivityOptions}
     * for how to build the Bundle supplied here; there are no supported definitions
     * for building it manually.
     *
     * @see Context#startActivity(Intent, Bundle)
     */
    @NonNull
    public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) {
        if (DEBUG_START_ACTIVITY) {
            Log.d(TAG, "startActivity: intent=" + intent + " options=" + options, new Throwable());
        }
        validateNotAppThread();

        final Activity activity;
        synchronized (mSync) {
            intent = new Intent(intent);

            ActivityInfo ai =
                    isSdkSandboxAllowedToStartActivities()
                            ? resolveActivityInfoForCtsInSandbox(intent)
                            : intent.resolveActivityInfo(getTargetContext().getPackageManager(), 0);
            if (ai == null) {
                throw new RuntimeException("Unable to resolve activity for: " + intent);
            }
            String myProc = mThread.getProcessName();
            if (!ai.processName.equals(myProc)) {
                // todo: if this intent is ambiguous, look here to see if
                // there is a single match that is in our package.
                throw new RuntimeException("Intent in process "
                        + myProc + " resolved to different process "
                        + ai.processName + ": " + intent);
            }

            intent.setComponent(new ComponentName(
                    ai.applicationInfo.packageName, ai.name));
            final ActivityWaiter aw = new ActivityWaiter(intent);

            if (mWaitingActivities == null) {
                mWaitingActivities = new ArrayList();
            }
            mWaitingActivities.add(aw);

            getTargetContext().startActivity(intent, options);

            do {
                try {
                    mSync.wait();
                } catch (InterruptedException e) {
                }
            } while (mWaitingActivities.contains(aw));
            activity = aw.activity;
        }

        // Do not call this method within mSync, lest it could block the main thread.
        waitForEnterAnimationComplete(activity);

        // Apply an empty transaction to ensure SF has a chance to update before
        // the Activity is ready (b/138263890).
        try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
            t.apply(true);
        }
        return activity;
    }

    /**
     * Information about a particular kind of Intent that is being monitored.
     * An instance of this class is added to the 
     * current instrumentation through {@link #addMonitor}; after being added, 
     * when a new activity is being started the monitor will be checked and, if 
     * matching, its hit count updated and (optionally) the call stopped and a 
     * canned result returned.
     * 
     * <p>An ActivityMonitor can also be used to look for the creation of an
     * activity, through the {@link #waitForActivity} method.  This will return
     * after a matching activity has been created with that activity object.
     */
    public static class ActivityMonitor {
        private final IntentFilter mWhich;
        private final String mClass;
        private final ActivityResult mResult;
        private final boolean mBlock;
        private final boolean mIgnoreMatchingSpecificIntents;


        // This is protected by 'Instrumentation.this.mSync'.
        /*package*/ int mHits = 0;

        // This is protected by 'this'.
        /*package*/ Activity mLastActivity = null;

        /**
         * Create a new ActivityMonitor that looks for a particular kind of 
         * intent to be started.
         *
         * @param which The set of intents this monitor is responsible for.
         * @param result A canned result to return if the monitor is hit; can 
         *               be null.
         * @param block Controls whether the monitor should block the activity 
         *              start (returning its canned result) or let the call
         *              proceed.
         *  
         * @see Instrumentation#addMonitor 
         */
        public ActivityMonitor(
            IntentFilter which, ActivityResult result, boolean block) {
            mWhich = which;
            mClass = null;
            mResult = result;
            mBlock = block;
            mIgnoreMatchingSpecificIntents = false;
        }

        /**
         * Create a new ActivityMonitor that looks for a specific activity 
         * class to be started. 
         *  
         * @param cls The activity class this monitor is responsible for.
         * @param result A canned result to return if the monitor is hit; can 
         *               be null.
         * @param block Controls whether the monitor should block the activity 
         *              start (returning its canned result) or let the call
         *              proceed.
         *  
         * @see Instrumentation#addMonitor 
         */
        public ActivityMonitor(
            String cls, ActivityResult result, boolean block) {
            mWhich = null;
            mClass = cls;
            mResult = result;
            mBlock = block;
            mIgnoreMatchingSpecificIntents = false;
        }

        /**
         * Create a new ActivityMonitor that can be used for intercepting any activity to be
         * started.
         *
         * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on
         * instances created using this constructor to see if it is a hit.
         *
         * @see #onStartActivity(Intent)
         */
        public ActivityMonitor() {
            mWhich = null;
            mClass = null;
            mResult = null;
            mBlock = false;
            mIgnoreMatchingSpecificIntents = true;
        }

        /**
         * @return true if this monitor is used for intercepting any started activity by calling
         *         into {@link #onStartActivity(Intent)}, false if this monitor is only used
         *         for specific intents corresponding to the intent filter or activity class
         *         passed in the constructor.
         */
        final boolean ignoreMatchingSpecificIntents() {
            return mIgnoreMatchingSpecificIntents;
        }

        /**
         * Retrieve the filter associated with this ActivityMonitor.
         */
        public final IntentFilter getFilter() {
            return mWhich;
        }

        /**
         * Retrieve the result associated with this ActivityMonitor, or null if 
         * none. 
         */
        public final ActivityResult getResult() {
            return mResult;
        }

        /**
         * Check whether this monitor blocks activity starts (not allowing the 
         * actual activity to run) or allows them to execute normally. 
         */
        public final boolean isBlocking() {
            return mBlock;
        }

        /**
         * Retrieve the number of times the monitor has been hit so far.
         */
        public final int getHits() {
            return mHits;
        }

        /**
         * Retrieve the most recent activity class that was seen by this 
         * monitor. 
         */
        public final Activity getLastActivity() {
            return mLastActivity;
        }

        /**
         * Block until an Activity is created that matches this monitor, 
         * returning the resulting activity. 
         * 
         * @return Activity
         */
        public final Activity waitForActivity() {
            synchronized (this) {
                while (mLastActivity == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
                Activity res = mLastActivity;
                mLastActivity = null;
                return res;
            }
        }

        /**
         * Block until an Activity is created that matches this monitor, 
         * returning the resulting activity or till the timeOut period expires.
         * If the timeOut expires before the activity is started, return null. 
         * 
         * @param timeOut Time to wait in milliseconds before the activity is created.
         * 
         * @return Activity
         */
        public final Activity waitForActivityWithTimeout(long timeOut) {
            synchronized (this) {
                if (mLastActivity == null) {
                    try {
                        wait(timeOut);
                    } catch (InterruptedException e) {
                    }
                }
                if (mLastActivity == null) {
                    return null;
                } else {
                    Activity res = mLastActivity;
                    mLastActivity = null;
                    return res;
                }
            }
        }

        /**
         * This overload is used for notifying the {@link android.window.TaskFragmentOrganizer}
         * implementation internally about started activities.
         *
         * @see #onStartActivity(Intent)
         * @hide
         */
        public ActivityResult onStartActivity(@NonNull Context who, @NonNull Intent intent,
                @NonNull Bundle options) {
            return onStartActivity(intent);
        }

        /**
         * Used for intercepting any started activity.
         *
         * <p> A non-null return value here will be considered a hit for this monitor.
         * By default this will return {@code null} and subclasses can override this to return
         * a non-null value if the intent needs to be intercepted.
         *
         * <p> Whenever a new activity is started, this method will be called on instances created
         * using {@link #ActivityMonitor()} to check if there is a match. In case
         * of a match, the activity start will be blocked and the returned result will be used.
         *
         * @param intent The intent used for starting the activity.
         * @return The {@link ActivityResult} that needs to be used in case of a match.
         */
        public ActivityResult onStartActivity(Intent intent) {
            return null;
        }

        /**
         * This is called after starting an Activity and provides the result code that defined in
         * {@link ActivityManager}, like {@link ActivityManager#START_SUCCESS}.
         *
         * @param result the result code that returns after starting an Activity.
         * @param bOptions the bundle generated from {@link ActivityOptions} that originally
         *                 being used to start the Activity.
         * @hide
         */
        public void onStartActivityResult(int result, @NonNull Bundle bOptions) {}

        final boolean match(Context who,
                            Activity activity,
                            Intent intent) {
            if (mIgnoreMatchingSpecificIntents) {
                return false;
            }
            synchronized (this) {
                if (mWhich != null
                    && mWhich.match(who.getContentResolver(), intent,
                                    true, "Instrumentation") < 0) {
                    return false;
                }
                if (mClass != null) {
                    String cls = null;
                    if (activity != null) {
                        cls = activity.getClass().getName();
                    } else if (intent.getComponent() != null) {
                        cls = intent.getComponent().getClassName();
                    }
                    if (cls == null || !mClass.equals(cls)) {
                        return false;
                    }
                }
                if (activity != null) {
                    mLastActivity = activity;
                    notifyAll();
                }
                return true;
            }
        }
    }

    /**
     * Add a new {@link ActivityMonitor} that will be checked whenever an 
     * activity is started.  The monitor is added 
     * after any existing ones; the monitor will be hit only if none of the 
     * existing monitors can themselves handle the Intent. 
     *  
     * @param monitor The new ActivityMonitor to see. 
     *  
     * @see #addMonitor(IntentFilter, ActivityResult, boolean) 
     * @see #checkMonitorHit 
     */
    public void addMonitor(ActivityMonitor monitor) {
        synchronized (mSync) {
            if (mActivityMonitors == null) {
                mActivityMonitors = new ArrayList();
            }
            mActivityMonitors.add(monitor);
        }
    }

    /**
     * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that 
     * creates an intent filter matching {@link ActivityMonitor} for you and 
     * returns it. 
     *  
     * @param filter The set of intents this monitor is responsible for.
     * @param result A canned result to return if the monitor is hit; can 
     *               be null.
     * @param block Controls whether the monitor should block the activity 
     *              start (returning its canned result) or let the call
     *              proceed.
     * 
     * @return The newly created and added activity monitor. 
     *  
     * @see #addMonitor(ActivityMonitor) 
     * @see #checkMonitorHit 
     */
    public ActivityMonitor addMonitor(
        IntentFilter filter, ActivityResult result, boolean block) {
        ActivityMonitor am = new ActivityMonitor(filter, result, block);
        addMonitor(am);
        return am;
    }

    /**
     * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that 
     * creates a class matching {@link ActivityMonitor} for you and returns it.
     *  
     * @param cls The activity class this monitor is responsible for.
     * @param result A canned result to return if the monitor is hit; can 
     *               be null.
     * @param block Controls whether the monitor should block the activity 
     *              start (returning its canned result) or let the call
     *              proceed.
     * 
     * @return The newly created and added activity monitor. 
     *  
     * @see #addMonitor(ActivityMonitor) 
     * @see #checkMonitorHit 
     */
    public ActivityMonitor addMonitor(
        String cls, ActivityResult result, boolean block) {
        ActivityMonitor am = new ActivityMonitor(cls, result, block);
        addMonitor(am);
        return am;
    }

    /**
     * Test whether an existing {@link ActivityMonitor} has been hit.  If the 
     * monitor has been hit at least <var>minHits</var> times, then it will be 
     * removed from the activity monitor list and true returned.  Otherwise it 
     * is left as-is and false is returned. 
     *  
     * @param monitor The ActivityMonitor to check.
     * @param minHits The minimum number of hits required.
     * 
     * @return True if the hit count has been reached, else false. 
     *  
     * @see #addMonitor 
     */
    public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
        waitForIdleSync();
        synchronized (mSync) {
            if (monitor.getHits() < minHits) {
                return false;
            }
            mActivityMonitors.remove(monitor);
        }
        return true;
    }

    /**
     * Wait for an existing {@link ActivityMonitor} to be hit.  Once the 
     * monitor has been hit, it is removed from the activity monitor list and 
     * the first created Activity object that matched it is returned.
     *  
     * @param monitor The ActivityMonitor to wait for.
     * 
     * @return The Activity object that matched the monitor.
     */
    public Activity waitForMonitor(ActivityMonitor monitor) {
        Activity activity = monitor.waitForActivity();
        synchronized (mSync) {
            mActivityMonitors.remove(monitor);
        }
        return activity;
    }

    /**
     * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
     * expires.  Once the monitor has been hit, it is removed from the activity 
     * monitor list and the first created Activity object that matched it is 
     * returned.  If the timeout expires, a null object is returned. 
     *
     * @param monitor The ActivityMonitor to wait for.
     * @param timeOut The timeout value in milliseconds.
     *
     * @return The Activity object that matched the monitor.
     */
    public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
        Activity activity = monitor.waitForActivityWithTimeout(timeOut);
        synchronized (mSync) {
            mActivityMonitors.remove(monitor);
        }
        return activity;
    }
    
    /**
     * Remove an {@link ActivityMonitor} that was previously added with 
     * {@link #addMonitor}.
     *  
     * @param monitor The monitor to remove.
     *  
     * @see #addMonitor 
     */
    public void removeMonitor(ActivityMonitor monitor) {
        synchronized (mSync) {
            mActivityMonitors.remove(monitor);
        }
    }

    /**
     * Execute a particular menu item.
     * 
     * @param targetActivity The activity in question.
     * @param id The identifier associated with the menu item.
     * @param flag Additional flags, if any.
     * @return Whether the invocation was successful (for example, it could be
     *         false if item is disabled).
     */
    public boolean invokeMenuActionSync(Activity targetActivity, 
                                    int id, int flag) {
        class MenuRunnable implements Runnable {
            private final Activity activity;
            private final int identifier;
            private final int flags;
            boolean returnValue;
            
            public MenuRunnable(Activity _activity, int _identifier,
                                    int _flags) {
                activity = _activity;
                identifier = _identifier;
                flags = _flags;
            }
            
            public void run() {
                Window win = activity.getWindow();
                
                returnValue = win.performPanelIdentifierAction(
                            Window.FEATURE_OPTIONS_PANEL,
                            identifier, 
                            flags);                
            }
            
        }        
        MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
        runOnMainSync(mr);
        return mr.returnValue;
    }

    /**
     * Show the context menu for the currently focused view and executes a
     * particular context menu item.
     * 
     * @param targetActivity The activity in question.
     * @param id The identifier associated with the context menu item.
     * @param flag Additional flags, if any.
     * @return Whether the invocation was successful (for example, it could be
     *         false if item is disabled).
     */
    public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
        validateNotAppThread();
        
        // Bring up context menu for current focus.
        // It'd be nice to do this through code, but currently ListView depends on
        //   long press to set metadata for its selected child
        
        final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER); 
        sendKeySync(downEvent);

        // Need to wait for long press
        waitForIdleSync();
        try {
            Thread.sleep(ViewConfiguration.getLongPressTimeout());
        } catch (InterruptedException e) {
            Log.e(TAG, "Could not sleep for long press timeout", e);
            return false;
        }

        final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER); 
        sendKeySync(upEvent);

        // Wait for context menu to appear
        waitForIdleSync();
        
        class ContextMenuRunnable implements Runnable {
            private final Activity activity;
            private final int identifier;
            private final int flags;
            boolean returnValue;
            
            public ContextMenuRunnable(Activity _activity, int _identifier,
                                    int _flags) {
                activity = _activity;
                identifier = _identifier;
                flags = _flags;
            }
            
            public void run() {
                Window win = activity.getWindow();
                returnValue = win.performContextMenuIdentifierAction(
                            identifier, 
                            flags);                
            }
            
        }        
        
        ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
        runOnMainSync(cmr);
        return cmr.returnValue;
    }
    
    /**
     * Sends the key events that result in the given text being typed into the currently focused
     * window, and waits for it to be processed.
     *
     * @param text The text to be sent.
     * @see #sendKeySync(KeyEvent)
     */
    public void sendStringSync(String text) {
        if (text == null) {
            return;
        }
        KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);

        KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());

        if (events != null) {
            for (int i = 0; i < events.length; i++) {
                // We have to change the time of an event before injecting it because
                // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
                // time stamp and the system rejects too old events. Hence, it is
                // possible for an event to become stale before it is injected if it
                // takes too long to inject the preceding ones.
                sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
            }
        }
    }

    /**
     * Sends a key event to the currently focused window, and waits for it to be processed.
     * <p>
     * This method blocks until the recipient has finished handling the event. Note that the
     * recipient may <em>not</em> have completely finished reacting from the event when this method
     * returns. For example, it may still be in the process of updating its display or UI contents
     * upon reacting to the injected event.
     *
     * @param event The event to send to the current focus.
     */
    public void sendKeySync(KeyEvent event) {
        validateNotAppThread();

        long downTime = event.getDownTime();
        long eventTime = event.getEventTime();
        int source = event.getSource();
        if (source == InputDevice.SOURCE_UNKNOWN) {
            source = InputDevice.SOURCE_KEYBOARD;
        }
        if (eventTime == 0) {
            eventTime = SystemClock.uptimeMillis();
        }
        if (downTime == 0) {
            downTime = eventTime;
        }
        KeyEvent newEvent = new KeyEvent(event);
        newEvent.setTime(downTime, eventTime);
        newEvent.setSource(source);
        newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
        setDisplayIfNeeded(newEvent);

        InputManagerGlobal.getInstance().injectInputEvent(newEvent,
                InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    }

    private void setDisplayIfNeeded(KeyEvent event) {
        if (!UserManager.isVisibleBackgroundUsersEnabled()) {
            return;
        }
        // In devices that support visible background users visible, the display id must be set to
        // reflect the display the user was started visible on, otherwise the event would be sent to
        // the main display (which would most likely fail the test).
        int eventDisplayId = event.getDisplayId();
        if (eventDisplayId != Display.INVALID_DISPLAY) {
            if (VERBOSE) {
                Log.v(TAG, "setDisplayIfNeeded(" + event + "): not changing display id as it's "
                        + "explicitly set to " + eventDisplayId);
            }
            return;
        }

        UserManager userManager = mInstrContext.getSystemService(UserManager.class);
        int userDisplayId = userManager.getMainDisplayIdAssignedToUser();
        if (VERBOSE) {
            Log.v(TAG, "setDisplayIfNeeded(" + event + "): eventDisplayId=" + eventDisplayId
                    + ", user=" + mInstrContext.getUser() + ", userDisplayId=" + userDisplayId);
        }
        if (userDisplayId == Display.INVALID_DISPLAY) {
            Log.e(TAG, "setDisplayIfNeeded(" + event + "): UserManager returned INVALID_DISPLAY as "
                    + "display assigned to user " + mInstrContext.getUser());
            return;

        }

        event.setDisplayId(userDisplayId);
    }

    /**
     * Sends up and down key events with the given key code to the currently focused window, and
     * waits for it to be processed.
     * 
     * @param keyCode The key code for the events to send.
     * @see #sendKeySync(KeyEvent)
     */
    public void sendKeyDownUpSync(int keyCode) {
        sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
        sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
    }

    /**
     * Sends up and down key events with the given key code to the currently focused window, and
     * waits for it to be processed.
     * <p>
     * Equivalent to {@link #sendKeyDownUpSync(int)}.
     *
     * @param keyCode The key code of the character to send.
     * @see #sendKeySync(KeyEvent)
     */
    public void sendCharacterSync(int keyCode) {
        sendKeyDownUpSync(keyCode);
    }

    /**
     * Dispatches a pointer event into a window owned by the instrumented application, and waits for
     * it to be processed.
     * <p>
     * If the motion event being injected is targeted at a window that is not owned by the
     * instrumented application, the input injection will fail. See {@link #getUiAutomation()} for
     * injecting events into all windows.
     * <p>
     * This method blocks until the recipient has finished handling the event. Note that the
     * recipient may <em>not</em> have completely finished reacting from the event when this method
     * returns. For example, it may still be in the process of updating its display or UI contents
     * upon reacting to the injected event.
     * 
     * @param event A motion event describing the pointer action.  (As noted in 
     * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 
     * {@link SystemClock#uptimeMillis()} as the timebase.
     */
    public void sendPointerSync(MotionEvent event) {
        validateNotAppThread();
        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
        }

        syncInputTransactionsAndInjectEventIntoSelf(event);
    }

    private void syncInputTransactionsAndInjectEventIntoSelf(MotionEvent event) {
        final boolean syncBefore = event.getAction() == MotionEvent.ACTION_DOWN
                || event.isFromSource(InputDevice.SOURCE_MOUSE);
        final boolean syncAfter = event.getAction() == MotionEvent.ACTION_UP;

        try {
            if (syncBefore) {
                WindowManagerGlobal.getWindowManagerService()
                        .syncInputTransactions(true /*waitForAnimations*/);
            }

            // Direct the injected event into windows owned by the instrumentation target.
            InputManagerGlobal.getInstance().injectInputEvent(
                    event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH, Process.myUid());

            if (syncAfter) {
                WindowManagerGlobal.getWindowManagerService()
                        .syncInputTransactions(true /*waitForAnimations*/);
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Dispatches a trackball event into the currently focused window, and waits for it to be
     * processed.
     * <p>
     * This method blocks until the recipient has finished handling the event. Note that the
     * recipient may <em>not</em> have completely finished reacting from the event when this method
     * returns. For example, it may still be in the process of updating its display or UI contents
     * upon reacting to the injected event.
     *
     * @param event A motion event describing the trackball action.  (As noted in 
     * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 
     * {@link SystemClock#uptimeMillis()} as the timebase.
     */
    public void sendTrackballEventSync(MotionEvent event) {
        validateNotAppThread();
        if (!event.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
            event.setSource(InputDevice.SOURCE_TRACKBALL);
        }
        InputManagerGlobal.getInstance().injectInputEvent(event,
                InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    }

    /**
     * Perform instantiation of the process's {@link Application} object.  The
     * default implementation provides the normal system behavior.
     * 
     * @param cl The ClassLoader with which to instantiate the object.
     * @param className The name of the class implementing the Application
     *                  object.
     * @param context The context to initialize the application with
     * 
     * @return The newly instantiated Application object.
     */
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
    
    /**
     * Perform instantiation of the process's {@link Application} object.  The
     * default implementation provides the normal system behavior.
     * 
     * @param clazz The class used to create an Application object from.
     * @param context The context to initialize the application with
     * 
     * @return The newly instantiated Application object.
     */
    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

    /**
     * Perform calling of the application's {@link Application#onCreate}
     * method.  The default implementation simply calls through to that method.
     *
     * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
     * Often instrumentation tests start their test thread in onCreate(); you
     * need to be careful of races between these.  (Well between it and
     * everything else, but let's start here.)
     *
     * @param app The application being created.
     */
    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }
    
    /**
     * Perform instantiation of an {@link Activity} object.  This method is intended for use with
     * unit tests, such as android.test.ActivityUnitTestCase.  The activity will be useable
     * locally but will be missing some of the linkages necessary for use within the system.
     * 
     * @param clazz The Class of the desired Activity
     * @param context The base context for the activity to use
     * @param token The token for this activity to communicate with
     * @param application The application object (if any)
     * @param intent The intent that started this Activity
     * @param info ActivityInfo from the manifest
     * @param title The title, typically retrieved from the ActivityInfo record
     * @param parent The parent Activity (if any)
     * @param id The embedded Id (if any)
     * @param lastNonConfigurationInstance Arbitrary object that will be
     * available via {@link Activity#getLastNonConfigurationInstance()
     * Activity.getLastNonConfigurationInstance()}.
     * @return Returns the instantiated activity
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public Activity newActivity(Class<?> clazz, Context context, 
            IBinder token, Application application, Intent intent, ActivityInfo info, 
            CharSequence title, Activity parent, String id,
            Object lastNonConfigurationInstance) throws InstantiationException,
            IllegalAccessException {
        Activity activity = (Activity)clazz.newInstance();
        ActivityThread aThread = null;
        // Activity.attach expects a non-null Application Object.
        if (application == null) {
            application = new Application();
        }
        activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
                info, title, parent, id,
                (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
                new Configuration(), null /* referrer */, null /* voiceInteractor */,
                null /* window */, null /* activityCallback */, null /*assistToken*/,
                null /*shareableActivityToken*/);
        return activity;
    }

    /**
     * Perform instantiation of the process's {@link Activity} object.  The
     * default implementation provides the normal system behavior.
     * 
     * @param cl The ClassLoader with which to instantiate the object.
     * @param className The name of the class implementing the Activity
     *                  object.
     * @param intent The Intent object that specified the activity class being
     *               instantiated.
     * 
     * @return The newly instantiated Activity object.
     */
    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }

    private AppComponentFactory getFactory(String pkg) {
        if (pkg == null) {
            Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
            return AppComponentFactory.DEFAULT;
        }
        if (mThread == null) {
            Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
                    + " disabling AppComponentFactory", new Throwable());
            return AppComponentFactory.DEFAULT;
        }
        LoadedApk apk = mThread.peekPackageInfo(pkg, true);
        // This is in the case of starting up "android".
        if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
        return apk.getAppFactory();
    }

    /**
     * This should be called before {@link #checkStartActivityResult(int, Object)}, because
     * exceptions might be thrown while checking the results.
     */
    private void notifyStartActivityResult(int result, @Nullable Bundle options) {
        if (mActivityMonitors == null) {
            return;
        }
        synchronized (mSync) {
            final int size = mActivityMonitors.size();
            for (int i = 0; i < size; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.ignoreMatchingSpecificIntents()) {
                    if (options == null) {
                        options = ActivityOptions.makeBasic().toBundle();
                    }
                    am.onStartActivityResult(result, options);
                }
            }
        }
    }

    private void prePerformCreate(Activity activity) {
        if (mWaitingActivities != null) {
            synchronized (mSync) {
                final int N = mWaitingActivities.size();
                for (int i=0; i<N; i++) {
                    final ActivityWaiter aw = mWaitingActivities.get(i);
                    final Intent intent = aw.intent;
                    if (intent.filterEquals(activity.getIntent())) {
                        aw.activity = activity;
                        mMessageQueue.addIdleHandler(new ActivityGoing(aw));
                    }
                }
            }
        }
    }

    private void postPerformCreate(Activity activity) {
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

    /**
     * Perform calling of an activity's {@link Activity#onCreate}
     * method.  The default implementation simply calls through to that method.
     *
     * @param activity The activity being created.
     * @param icicle The previously frozen state (or null) to pass through to onCreate().
     */
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

    /**
     * Perform calling of an activity's {@link Activity#onCreate}
     * method.  The default implementation simply calls through to that method.
     *  @param activity The activity being created.
     * @param icicle The previously frozen state (or null) to pass through to
     * @param persistentState The previously persisted state (or null)
     */
    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }
    
    public void callActivityOnDestroy(Activity activity) {
      // TODO: the following block causes intermittent hangs when using startActivity
      // temporarily comment out until root cause is fixed (bug 2630683)
//      if (mWaitingActivities != null) {
//          synchronized (mSync) {
//              final int N = mWaitingActivities.size();
//              for (int i=0; i<N; i++) {
//                  final ActivityWaiter aw = mWaitingActivities.get(i);
//                  final Intent intent = aw.intent;
//                  if (intent.filterEquals(activity.getIntent())) {
//                      aw.activity = activity;
//                      mMessageQueue.addIdleHandler(new ActivityGoing(aw));
//                  }
//              }
//          }
//      }
      
      activity.performDestroy();
  }

    /**
     * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
     * method.  The default implementation simply calls through to that method.
     *
     * @param activity The activity being restored.
     * @param savedInstanceState The previously saved state being restored.
     */
    public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
            @NonNull Bundle savedInstanceState) {
        activity.performRestoreInstanceState(savedInstanceState);
    }

    /**
     * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
     * method.  The default implementation simply calls through to that method.
     *
     * @param activity The activity being restored.
     * @param savedInstanceState The previously saved state being restored (or null).
     * @param persistentState The previously persisted state (or null)
     */
    public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState,
            @Nullable PersistableBundle persistentState) {
        activity.performRestoreInstanceState(savedInstanceState, persistentState);
    }

    /**
     * Perform calling of an activity's {@link Activity#onPostCreate} method.
     * The default implementation simply calls through to that method.
     *
     * @param activity The activity being created.
     * @param savedInstanceState The previously saved state (or null) to pass through to
     *               onPostCreate().
     */
    public void callActivityOnPostCreate(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState) {
        activity.onPostCreate(savedInstanceState);
    }

    /**
     * Perform calling of an activity's {@link Activity#onPostCreate} method.
     * The default implementation simply calls through to that method.
     *
     * @param activity The activity being created.
     * @param savedInstanceState The previously frozen state (or null) to pass through to
     *               onPostCreate().
     * @param persistentState The previously persisted state (or null)
     */
    public void callActivityOnPostCreate(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState,
            @Nullable PersistableBundle persistentState) {
        activity.onPostCreate(savedInstanceState, persistentState);
    }

    /**
     * Perform calling of an activity's {@link Activity#onNewIntent}
     * method.  The default implementation simply calls through to that method.
     * 
     * @param activity The activity receiving a new Intent.
     * @param intent The new intent being received.
     */
    public void callActivityOnNewIntent(Activity activity, Intent intent) {
        activity.performNewIntent(intent);
    }

    /**
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
        final String oldReferrer = activity.mReferrer;
        try {
            if (intent != null) {
                activity.mReferrer = intent.mReferrer;
            }
            callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
        } finally {
            activity.mReferrer = oldReferrer;
        }
    }

    /**
     * Perform calling of an activity's {@link Activity#onStart}
     * method.  The default implementation simply calls through to that method.
     * 
     * @param activity The activity being started.
     */
    public void callActivityOnStart(Activity activity) {
        activity.onStart();
    }

    /**
     * Perform calling of an activity's {@link Activity#onRestart}
     * method.  The default implementation simply calls through to that method.
     * 
     * @param activity The activity being restarted.
     */
    public void callActivityOnRestart(Activity activity) {
        activity.onRestart();
    }

    /**
     * Perform calling of an activity's {@link Activity#onResume} method.  The
     * default implementation simply calls through to that method.
     * 
     * @param activity The activity being resumed.
     */
    public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        activity.onResume();
        
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

    /**
     * Perform calling of an activity's {@link Activity#onStop}
     * method.  The default implementation simply calls through to that method.
     * 
     * @param activity The activity being stopped.
     */
    public void callActivityOnStop(Activity activity) {
        activity.onStop();
    }

    /**
     * Perform calling of an activity's {@link Activity#onSaveInstanceState}
     * method.  The default implementation simply calls through to that method.
     *
     * @param activity The activity being saved.
     * @param outState The bundle to pass to the call.
     */
    public void callActivityOnSaveInstanceState(@NonNull Activity activity,
            @NonNull Bundle outState) {
        activity.performSaveInstanceState(outState);
    }

    /**
     * Perform calling of an activity's {@link Activity#onSaveInstanceState}
     * method.  The default implementation simply calls through to that method.
     *  @param activity The activity being saved.
     * @param outState The bundle to pass to the call.
     * @param outPersistentState The persistent bundle to pass to the call.
     */
    public void callActivityOnSaveInstanceState(@NonNull Activity activity,
            @NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
        activity.performSaveInstanceState(outState, outPersistentState);
    }

    /**
     * Perform calling of an activity's {@link Activity#onPause} method.  The
     * default implementation simply calls through to that method.
     * 
     * @param activity The activity being paused.
     */
    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }
    
    /**
     * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
     * The default implementation simply calls through to that method.
     * 
     * @param activity The activity being notified that the user has navigated away
     */
    public void callActivityOnUserLeaving(Activity activity) {
        activity.performUserLeaving();
    }

    /**
     * Perform calling of an activity's {@link Activity#onPictureInPictureRequested} method.
     * The default implementation simply calls through to that method.
     *
     * @param activity The activity being notified that picture-in-picture is being requested.
     */
    public void callActivityOnPictureInPictureRequested(@NonNull Activity activity) {
        activity.onPictureInPictureRequested();
    }
    
    /*
     * Starts allocation counting. This triggers a gc and resets the counts.
     *
     * @deprecated Accurate counting is a burden on the runtime and may be removed.
     */
    @Deprecated
    public void startAllocCounting() {
        // Before we start trigger a GC and reset the debug counts. Run the 
        // finalizers and another GC before starting and stopping the alloc
        // counts. This will free up any objects that were just sitting around 
        // waiting for their finalizers to be run.
        Runtime.getRuntime().gc();
        Runtime.getRuntime().runFinalization();
        Runtime.getRuntime().gc();

        Debug.resetAllCounts();
        
        // start the counts
        Debug.startAllocCounting();
    }
    
    /*
     * Stops allocation counting.
     *
     * @deprecated Accurate counting is a burden on the runtime and may be removed.
     */
    @Deprecated
    public void stopAllocCounting() {
        Runtime.getRuntime().gc();
        Runtime.getRuntime().runFinalization();
        Runtime.getRuntime().gc();
        Debug.stopAllocCounting();
    }
    
    /**
     * If Results already contains Key, it appends Value to the key's ArrayList
     * associated with the key. If the key doesn't already exist in results, it
     * adds the key/value pair to results.
     */
    private void addValue(String key, int value, Bundle results) {
        if (results.containsKey(key)) {
            List<Integer> list = results.getIntegerArrayList(key);
            if (list != null) {
                list.add(value);
            }
        } else {
            ArrayList<Integer> list = new ArrayList<Integer>();
            list.add(value);
            results.putIntegerArrayList(key, list);
        }
    }

    /**
     * Returns a bundle with the current results from the allocation counting.
     */
    public Bundle getAllocCounts() {
        Bundle results = new Bundle();
        results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
        results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
        results.putLong("global_freed_count", Debug.getGlobalFreedCount());
        results.putLong("global_freed_size", Debug.getGlobalFreedSize());
        results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());    
        return results;
    }

    /**
     * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
     * reported are the number of send and the number of received transactions.
     */
    public Bundle getBinderCounts() {
        Bundle results = new Bundle();
        results.putLong("sent_transactions", Debug.getBinderSentTransactions());
        results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
        return results;
    }
    
    /**
     * Description of a Activity execution result to return to the original
     * activity.
     */
    public static final class ActivityResult {
        /**
         * Create a new activity result.  See {@link Activity#setResult} for 
         * more information. 
         *  
         * @param resultCode The result code to propagate back to the
         * originating activity, often RESULT_CANCELED or RESULT_OK
         * @param resultData The data to propagate back to the originating
         * activity.
         */
        public ActivityResult(int resultCode, Intent resultData) {
            mResultCode = resultCode;
            mResultData = resultData;
        }

        /**
         * Retrieve the result code contained in this result.
         */
        public int getResultCode() {
            return mResultCode;
        }

        /**
         * Retrieve the data contained in this result.
         */
        public Intent getResultData() {
            return mResultData;
        }

        private final int mResultCode;
        private final Intent mResultData;
    }

    /**
     * Execute a startActivity call made by the application.  The default 
     * implementation takes care of updating any active {@link ActivityMonitor}
     * objects and dispatches this call to the system activity manager; you can
     * override this to watch for the application to start an activity, and 
     * modify what happens when it does. 
     *
     * <p>This method returns an {@link ActivityResult} object, which you can 
     * use when intercepting application calls to avoid performing the start 
     * activity action but still return the result the application is 
     * expecting.  To do this, override this method to catch the call to start 
     * activity so that it returns a new ActivityResult containing the results 
     * you would like the application to see, and don't call up to the super 
     * class.  Note that an application is only expecting a result if 
     * <var>requestCode</var> is &gt;= 0.
     *
     * <p>This method throws {@link android.content.ActivityNotFoundException}
     * if there was no Activity found to run the given Intent.
     *
     * @param who The Context from which the activity is being started.
     * @param contextThread The main thread of the Context from which the activity
     *                      is being started.
     * @param token Internal token identifying to the system who is starting 
     *              the activity; may be null.
     * @param target Which activity is performing the start (and thus receiving 
     *               any result); may be null if this call is not being made
     *               from an activity.
     * @param intent The actual Intent to start.
     * @param requestCode Identifier for this request's result; less than zero 
     *                    if the caller is not expecting a result.
     * @param options Addition options.
     *
     * @return To force the return of a particular result, return an 
     *         ActivityResult object containing the desired data; otherwise
     *         return null.  The default implementation always returns null.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see Activity#startActivity(Intent)
     * @see Activity#startActivityForResult(Intent, int)
     *
     * {@hide}
     */
    @UnsupportedAppUsage
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        if (DEBUG_START_ACTIVITY) {
            Log.d(TAG, "startActivity: who=" + who + " source=" + target + " intent=" + intent
                    + " requestCode=" + requestCode + " options=" + options, new Throwable());
        }
        Objects.requireNonNull(intent);
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (isSdkSandboxAllowedToStartActivities()) {
            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        if (options == null) {
                            options = ActivityOptions.makeBasic().toBundle();
                        }
                        result = am.onStartActivity(who, intent, options);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                    target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

    /**
     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
     * but accepts an array of activities to be started.  Note that active
     * {@link ActivityMonitor} objects only match against the first activity in
     * the array.
     *
     * {@hide}
     */
    @UnsupportedAppUsage
    public void execStartActivities(Context who, IBinder contextThread,
            IBinder token, Activity target, Intent[] intents, Bundle options) {
        execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
                who.getUserId());
    }

    /**
     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
     * but accepts an array of activities to be started.  Note that active
     * {@link ActivityMonitor} objects only match against the first activity in
     * the array.
     *
     * @return The corresponding flag {@link ActivityManager#START_CANCELED},
     *         {@link ActivityManager#START_SUCCESS} etc. indicating whether the launch was
     *         successful.
     *
     * {@hide}
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public int execStartActivitiesAsUser(Context who, IBinder contextThread,
            IBinder token, Activity target, Intent[] intents, Bundle options,
            int userId) {
        if (DEBUG_START_ACTIVITY) {
            StringJoiner joiner = new StringJoiner(", ");
            for (Intent i : intents) {
                joiner.add(i.toString());
            }
            Log.d(TAG, "startActivities: who=" + who + " source=" + target + " userId=" + userId
                    + " intents=[" + joiner + "] options=" + options, new Throwable());
        }
        Objects.requireNonNull(intents);
        for (int i = intents.length - 1; i >= 0; i--) {
            Objects.requireNonNull(intents[i]);
        }
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (isSdkSandboxAllowedToStartActivities()) {
            for (Intent intent : intents) {
                adjustIntentForCtsInSdkSandboxInstrumentation(intent);
            }
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        if (options == null) {
                            options = ActivityOptions.makeBasic().toBundle();
                        }
                        result = am.onStartActivity(who, intents[0], options);
                    }
                    if (result != null) {
                        am.mHits++;
                        return ActivityManager.START_CANCELED;
                    } else if (am.match(who, null, intents[0])) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return ActivityManager.START_CANCELED;
                        }
                        break;
                    }
                }
            }
        }
        try {
            String[] resolvedTypes = new String[intents.length];
            for (int i=0; i<intents.length; i++) {
                intents[i].migrateExtraStreamToClipData(who);
                intents[i].prepareToLeaveProcess(who);
                resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
            }
            int result = ActivityTaskManager.getService().startActivities(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intents, resolvedTypes,
                    token, options, userId);
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intents[0]);
            return result;
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
    }

    /**
     * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
     * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
     * but for calls from a {@link Fragment}.
     *
     * @param who The Context from which the activity is being started.
     * @param contextThread The main thread of the Context from which the activity
     *                      is being started.
     * @param token Internal token identifying to the system who is starting
     *              the activity; may be null.
     * @param target Which element is performing the start (and thus receiving
     *               any result).
     * @param intent The actual Intent to start.
     * @param requestCode Identifier for this request's result; less than zero
     *                    if the caller is not expecting a result.
     *
     * @return To force the return of a particular result, return an
     *         ActivityResult object containing the desired data; otherwise
     *         return null.  The default implementation always returns null.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see Activity#startActivity(Intent)
     * @see Activity#startActivityForResult(Intent, int)
     *
     * {@hide}
     */
    @UnsupportedAppUsage
    public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
        if (DEBUG_START_ACTIVITY) {
            Log.d(TAG, "startActivity: who=" + who + " target=" + target
                    + " intent=" + intent + " requestCode=" + requestCode
                    + " options=" + options, new Throwable());
        }
        Objects.requireNonNull(intent);
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (isSdkSandboxAllowedToStartActivities()) {
            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        if (options == null) {
                            options = ActivityOptions.makeBasic().toBundle();
                        }
                        result = am.onStartActivity(who, intent, options);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token, target,
                    requestCode, 0, null, options);
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

    /**
     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
     * but for starting as a particular user.
     *
     * @param who The Context from which the activity is being started.
     * @param contextThread The main thread of the Context from which the activity
     *                      is being started.
     * @param token Internal token identifying to the system who is starting
     *              the activity; may be null.
     * @param target Which fragment is performing the start (and thus receiving
     *               any result).
     * @param intent The actual Intent to start.
     * @param requestCode Identifier for this request's result; less than zero
     *                    if the caller is not expecting a result.
     *
     * @return To force the return of a particular result, return an
     *         ActivityResult object containing the desired data; otherwise
     *         return null.  The default implementation always returns null.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see Activity#startActivity(Intent)
     * @see Activity#startActivityForResult(Intent, int)
     *
     * {@hide}
     */
    @UnsupportedAppUsage
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, String resultWho,
            Intent intent, int requestCode, Bundle options, UserHandle user) {
        if (DEBUG_START_ACTIVITY) {
            Log.d(TAG, "startActivity: who=" + who + " user=" + user + " intent=" + intent
                    + " requestCode=" + requestCode + " resultWho=" + resultWho
                    + " options=" + options, new Throwable());
        }
        Objects.requireNonNull(intent);
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (isSdkSandboxAllowedToStartActivities()) {
            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        if (options == null) {
                            options = ActivityOptions.makeBasic().toBundle();
                        }
                        result = am.onStartActivity(who, intent, options);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService().startActivityAsUser(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token, resultWho,
                    requestCode, 0, null, options, user.getIdentifier());
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

    /**
     * Special version!
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public ActivityResult execStartActivityAsCaller(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options,
            boolean ignoreTargetSecurity, int userId) {
        if (DEBUG_START_ACTIVITY) {
            Log.d(TAG, "startActivity: who=" + who + " source=" + target + " userId=" + userId
                    + " intent=" + intent + " requestCode=" + requestCode
                    + " ignoreTargetSecurity=" + ignoreTargetSecurity + " options=" + options,
                    new Throwable());
        }
        Objects.requireNonNull(intent);
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (isSdkSandboxAllowedToStartActivities()) {
            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        if (options == null) {
                            options = ActivityOptions.makeBasic().toBundle();
                        }
                        result = am.onStartActivity(who, intent, options);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService()
                    .startActivityAsCaller(whoThread, who.getOpPackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options,
                            ignoreTargetSecurity, userId);
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

    /**
     * Special version!
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void execStartActivityFromAppTask(
            Context who, IBinder contextThread, IAppTask appTask,
            Intent intent, Bundle options) {
        if (DEBUG_START_ACTIVITY) {
            Log.d(TAG, "startActivity: who=" + who + " intent=" + intent
                    + " options=" + options, new Throwable());
        }
        Objects.requireNonNull(intent);
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (isSdkSandboxAllowedToStartActivities()) {
            adjustIntentForCtsInSdkSandboxInstrumentation(intent);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        if (options == null) {
                            options = ActivityOptions.makeBasic().toBundle();
                        }
                        result = am.onStartActivity(who, intent, options);
                    }
                    if (result != null) {
                        am.mHits++;
                        return;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = appTask.startActivity(whoThread.asBinder(), who.getOpPackageName(),
                    who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), options);
            notifyStartActivityResult(result, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return;
    }

    /*package*/ final void init(ActivityThread thread,
            Context instrContext, Context appContext, ComponentName component, 
            IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
        mThread = thread;
        mMessageQueue = mThread.getLooper().myQueue();
        mInstrContext = instrContext;
        mAppContext = appContext;
        mComponent = component;
        mWatcher = watcher;
        mUiAutomationConnection = uiAutomationConnection;
    }

    /**
     * Only sets the ActivityThread up, keeps everything else null because app is not being
     * instrumented.
     */
    final void basicInit(ActivityThread thread) {
        mThread = thread;
    }

    /** @hide */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public static void checkStartActivityResult(int res, Object intent) {
        if (!ActivityManager.isStartResultFatalError(res)) {
            return;
        }

        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml"
                            + ", or does your intent not match its declared <intent-filter>?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException(
                        "Starting under voice control not allowed for: " + intent);
            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startVoiceActivity does not match active session");
            case ActivityManager.START_VOICE_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start voice activity on a hidden session");
            case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startAssistantActivity does not match active session");
            case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start assistant activity on a hidden session");
            case ActivityManager.START_CANCELED:
                throw new AndroidRuntimeException("Activity could not be started for "
                        + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

    private final void validateNotAppThread() {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            throw new RuntimeException(
                "This method can not be called from the main application thread");
        }
    }

    /**
     * Gets the {@link UiAutomation} instance with no flags set.
     * <p>
     * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
     * work across application boundaries while the APIs exposed by the instrumentation
     * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
     * not allow you to inject the event in an app different from the instrumentation
     * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
     * will work regardless of the current application.
     * </p>
     * <p>
     * A typical test case should be using either the {@link UiAutomation} or
     * {@link Instrumentation} APIs. Using both APIs at the same time is not
     * a mistake by itself but a client has to be aware of the APIs limitations.
     * </p>
     * <p>
     * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
     * flags, the flags on that instance will be changed, and then it will be returned.
     * </p>
     * <p>
     * Compatibility mode: This method is infallible for apps targeted for
     * {@link Build.VERSION_CODES#R} and earlier versions; for apps targeted for later versions, it
     * will return null if {@link UiAutomation} fails to connect. The caller can check the return
     * value and retry on error.
     * </p>
     *
     * @return The UI automation instance.
     *
     * @see UiAutomation
     */
    public UiAutomation getUiAutomation() {
        return getUiAutomation(0);
    }

    /**
     * Gets the {@link UiAutomation} instance with flags set.
     * <p>
     * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
     * work across application boundaries while the APIs exposed by the instrumentation
     * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
     * not allow you to inject the event in an app different from the instrumentation
     * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
     * will work regardless of the current application.
     * </p>
     * <p>
     * A typical test case should be using either the {@link UiAutomation} or
     * {@link Instrumentation} APIs. Using both APIs at the same time is not
     * a mistake by itself but a client has to be aware of the APIs limitations.
     * </p>
     * <p>
     * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
     * changed, and then it will be returned.
     * </p>
     * <p>
     * Compatibility mode: This method is infallible for apps targeted for
     * {@link Build.VERSION_CODES#R} and earlier versions; for apps targeted for later versions, it
     * will return null if {@link UiAutomation} fails to connect. The caller can check the return
     * value and retry on error.
     * </p>
     *
     * @param flags The flags to be passed to the UiAutomation, for example
     *        {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES},
     *        {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY}.
     *
     * @return The UI automation instance.
     *
     * @see UiAutomation
     */
    public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
        boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());

        if (mUiAutomationConnection != null) {
            if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
                return mUiAutomation;
            }
            if (mustCreateNewAutomation) {
                mUiAutomation = new UiAutomation(getTargetContext(), mUiAutomationConnection);
            } else {
                mUiAutomation.disconnect();
            }
            if (getTargetContext().getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R) {
                mUiAutomation.connect(flags);
                return mUiAutomation;
            }
            final long startUptime = SystemClock.uptimeMillis();
            try {
                mUiAutomation.connectWithTimeout(flags, CONNECT_TIMEOUT_MILLIS);
                return mUiAutomation;
            } catch (TimeoutException e) {
                final long waited = SystemClock.uptimeMillis() - startUptime;
                Log.e(TAG, "Unable to connect to UiAutomation. Waited for " + waited + " ms", e);
                mUiAutomation.destroy();
                mUiAutomation = null;
            }
        }
        return null;
    }

    /**
     * Takes control of the execution of messages on the specified looper until
     * {@link TestLooperManager#release} is called.
     */
    public TestLooperManager acquireLooperManager(Looper looper) {
        checkInstrumenting("acquireLooperManager");
        return new TestLooperManager(looper);
    }

    private final class InstrumentationThread extends Thread {
        public InstrumentationThread(String name) {
            super(name);
        }
        public void run() {
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
            } catch (RuntimeException e) {
                Log.w(TAG, "Exception setting priority of instrumentation thread "
                        + Process.myTid(), e);
            }
            if (mAutomaticPerformanceSnapshots) {
                startPerformanceSnapshot();
            }
            onStart();
        }
    }

    private static final class EmptyRunnable implements Runnable {
        public void run() {
        }
    }

    private static final class SyncRunnable implements Runnable {
        private final Runnable mTarget;
        private boolean mComplete;

        public SyncRunnable(Runnable target) {
            mTarget = target;
        }

        public void run() {
            mTarget.run();
            synchronized (this) {
                mComplete = true;
                notifyAll();
            }
        }

        public void waitForComplete() {
            synchronized (this) {
                while (!mComplete) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }

    private static final class ActivityWaiter {
        public final Intent intent;
        public Activity activity;

        public ActivityWaiter(Intent _intent) {
            intent = _intent;
        }
    }

    private final class ActivityGoing implements MessageQueue.IdleHandler {
        private final ActivityWaiter mWaiter;

        public ActivityGoing(ActivityWaiter waiter) {
            mWaiter = waiter;
        }

        public final boolean queueIdle() {
            synchronized (mSync) {
                mWaitingActivities.remove(mWaiter);
                mSync.notifyAll();
            }
            return false;
        }
    }

    private static final class Idler implements MessageQueue.IdleHandler {
        private final Runnable mCallback;
        private boolean mIdle;

        public Idler(Runnable callback) {
            mCallback = callback;
            mIdle = false;
        }

        public final boolean queueIdle() {
            if (mCallback != null) {
                mCallback.run();
            }
            synchronized (this) {
                mIdle = true;
                notifyAll();
            }
            return false;
        }

        public void waitForIdle() {
            synchronized (this) {
                while (!mIdle) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }
}
