1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import static android.app.Activity.RESULT_CANCELED;
20import static android.app.ActivityManager.START_ABORTED;
21import static android.app.ActivityManager.START_CANCELED;
22import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
23import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
24import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
25import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
26import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
27import static android.app.ActivityManager.START_SUCCESS;
28import static android.app.ActivityManager.START_TASK_TO_FRONT;
29import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
30import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
31import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
32import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
33import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
34import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
35import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
36import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
37import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
38import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
39import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
40import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
41import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
42import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
43import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
44import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
45import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
46import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
47import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
48import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
49import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
50import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
51import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
52import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
53import static android.view.Display.DEFAULT_DISPLAY;
54import static android.view.Display.INVALID_DISPLAY;
55import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
56import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
62import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
65import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
66import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
67import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
68import static com.android.server.am.ActivityManagerService.ANIMATE;
69import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
70import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
71import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
72import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
73import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
74import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
75import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
76import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
77
78import android.annotation.NonNull;
79import android.annotation.Nullable;
80import android.app.ActivityManager;
81import android.app.ActivityOptions;
82import android.app.IApplicationThread;
83import android.app.PendingIntent;
84import android.app.ProfilerInfo;
85import android.app.WaitResult;
86import android.content.IIntentSender;
87import android.content.Intent;
88import android.content.IntentSender;
89import android.content.pm.ActivityInfo;
90import android.content.pm.ApplicationInfo;
91import android.content.pm.AuxiliaryResolveInfo;
92import android.content.pm.PackageManager;
93import android.content.pm.ResolveInfo;
94import android.content.pm.UserInfo;
95import android.content.res.Configuration;
96import android.graphics.Rect;
97import android.os.Binder;
98import android.os.Bundle;
99import android.os.IBinder;
100import android.os.RemoteException;
101import android.os.SystemClock;
102import android.os.UserHandle;
103import android.os.UserManager;
104import android.service.voice.IVoiceInteractionSession;
105import android.text.TextUtils;
106import android.util.EventLog;
107import android.util.Pools.SynchronizedPool;
108import android.util.Slog;
109
110import com.android.internal.annotations.VisibleForTesting;
111import com.android.internal.app.HeavyWeightSwitcherActivity;
112import com.android.internal.app.IVoiceInteractor;
113import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
114import com.android.server.am.LaunchParamsController.LaunchParams;
115import com.android.server.pm.InstantAppResolver;
116
117import java.io.PrintWriter;
118import java.text.DateFormat;
119import java.util.Date;
120
121/**
122 * Controller for interpreting how and then launching an activity.
123 *
124 * This class collects all the logic for determining how an intent and flags should be turned into
125 * an activity and associated task and stack.
126 */
127class ActivityStarter {
128    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
129    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
130    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
131    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
132    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
133    private static final int INVALID_LAUNCH_MODE = -1;
134
135    private final ActivityManagerService mService;
136    private final ActivityStackSupervisor mSupervisor;
137    private final ActivityStartInterceptor mInterceptor;
138    private final ActivityStartController mController;
139
140    // Share state variable among methods when starting an activity.
141    private ActivityRecord mStartActivity;
142    private Intent mIntent;
143    private int mCallingUid;
144    private ActivityOptions mOptions;
145
146    private int mLaunchMode;
147    private boolean mLaunchTaskBehind;
148    private int mLaunchFlags;
149
150    private LaunchParams mLaunchParams = new LaunchParams();
151
152    private ActivityRecord mNotTop;
153    private boolean mDoResume;
154    private int mStartFlags;
155    private ActivityRecord mSourceRecord;
156
157    // The display to launch the activity onto, barring any strong reason to do otherwise.
158    private int mPreferredDisplayId;
159
160    private TaskRecord mInTask;
161    private boolean mAddingToTask;
162    private TaskRecord mReuseTask;
163
164    private ActivityInfo mNewTaskInfo;
165    private Intent mNewTaskIntent;
166    private ActivityStack mSourceStack;
167    private ActivityStack mTargetStack;
168    private boolean mMovedToFront;
169    private boolean mNoAnimation;
170    private boolean mKeepCurTransition;
171    private boolean mAvoidMoveToFront;
172
173    // We must track when we deliver the new intent since multiple code paths invoke
174    // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
175    // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
176    // delivered at most once.
177    private boolean mIntentDelivered;
178
179    private IVoiceInteractionSession mVoiceSession;
180    private IVoiceInteractor mVoiceInteractor;
181
182    // Last activity record we attempted to start
183    private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
184    // The result of the last activity we attempted to start.
185    private int mLastStartActivityResult;
186    // Time in milli seconds we attempted to start the last activity.
187    private long mLastStartActivityTimeMs;
188    // The reason we were trying to start the last activity
189    private String mLastStartReason;
190
191    /*
192     * Request details provided through setter methods. Should be reset after {@link #execute()}
193     * to avoid unnecessarily retaining parameters. Note that the request is ignored when
194     * {@link #startResolvedActivity} is invoked directly.
195     */
196    private Request mRequest = new Request();
197
198    /**
199     * An interface that to provide {@link ActivityStarter} instances to the controller. This is
200     * used by tests to inject their own starter implementations for verification purposes.
201     */
202    @VisibleForTesting
203    interface Factory {
204        /**
205         * Sets the {@link ActivityStartController} to be passed to {@link ActivityStarter}.
206         */
207        void setController(ActivityStartController controller);
208
209        /**
210         * Generates an {@link ActivityStarter} that is ready to handle a new start request.
211         * @param controller The {@link ActivityStartController} which the starter who will own
212         *                   this instance.
213         * @return an {@link ActivityStarter}
214         */
215        ActivityStarter obtain();
216
217        /**
218         * Recycles a starter for reuse.
219         */
220        void recycle(ActivityStarter starter);
221    }
222
223    /**
224     * Default implementation of {@link StarterFactory}.
225     */
226    static class DefaultFactory implements Factory {
227        /**
228         * The maximum count of starters that should be active at one time:
229         * 1. last ran starter (for logging and post activity processing)
230         * 2. current running starter
231         * 3. starter from re-entry in (2)
232         */
233        private final int MAX_STARTER_COUNT = 3;
234
235        private ActivityStartController mController;
236        private ActivityManagerService mService;
237        private ActivityStackSupervisor mSupervisor;
238        private ActivityStartInterceptor mInterceptor;
239
240        private SynchronizedPool<ActivityStarter> mStarterPool =
241                new SynchronizedPool<>(MAX_STARTER_COUNT);
242
243        DefaultFactory(ActivityManagerService service,
244                ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
245            mService = service;
246            mSupervisor = supervisor;
247            mInterceptor = interceptor;
248        }
249
250        @Override
251        public void setController(ActivityStartController controller) {
252            mController = controller;
253        }
254
255        @Override
256        public ActivityStarter obtain() {
257            ActivityStarter starter = mStarterPool.acquire();
258
259            if (starter == null) {
260                starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
261            }
262
263            return starter;
264        }
265
266        @Override
267        public void recycle(ActivityStarter starter) {
268            starter.reset(true /* clearRequest*/);
269            mStarterPool.release(starter);
270        }
271    }
272
273    /**
274     * Container for capturing initial start request details. This information is NOT reset until
275     * the {@link ActivityStarter} is recycled, allowing for multiple invocations with the same
276     * parameters.
277     *
278     * TODO(b/64750076): Investigate consolidating member variables of {@link ActivityStarter} with
279     * the request object. Note that some member variables are referenced in
280     * {@link #dump(PrintWriter, String)} and therefore cannot be cleared immediately after
281     * execution.
282     */
283    private static class Request {
284        private static final int DEFAULT_CALLING_UID = -1;
285        private static final int DEFAULT_CALLING_PID = 0;
286
287        IApplicationThread caller;
288        Intent intent;
289        Intent ephemeralIntent;
290        String resolvedType;
291        ActivityInfo activityInfo;
292        ResolveInfo resolveInfo;
293        IVoiceInteractionSession voiceSession;
294        IVoiceInteractor voiceInteractor;
295        IBinder resultTo;
296        String resultWho;
297        int requestCode;
298        int callingPid = DEFAULT_CALLING_UID;
299        int callingUid = DEFAULT_CALLING_PID;
300        String callingPackage;
301        int realCallingPid;
302        int realCallingUid;
303        int startFlags;
304        SafeActivityOptions activityOptions;
305        boolean ignoreTargetSecurity;
306        boolean componentSpecified;
307        boolean avoidMoveToFront;
308        ActivityRecord[] outActivity;
309        TaskRecord inTask;
310        String reason;
311        ProfilerInfo profilerInfo;
312        Configuration globalConfig;
313        int userId;
314        WaitResult waitResult;
315        int filterCallingUid;
316
317        /**
318         * If set to {@code true}, allows this activity start to look into
319         * {@link PendingRemoteAnimationRegistry}
320         */
321        boolean allowPendingRemoteAnimationRegistryLookup;
322
323        /**
324         * Indicates that we should wait for the result of the start request. This flag is set when
325         * {@link ActivityStarter#setMayWait(int)} is called.
326         * {@see ActivityStarter#startActivityMayWait}.
327         */
328        boolean mayWait;
329
330        /**
331         * Ensure constructed request matches reset instance.
332         */
333        Request() {
334            reset();
335        }
336
337        /**
338         * Sets values back to the initial state, clearing any held references.
339         */
340        void reset() {
341            caller = null;
342            intent = null;
343            ephemeralIntent = null;
344            resolvedType = null;
345            activityInfo = null;
346            resolveInfo = null;
347            voiceSession = null;
348            voiceInteractor = null;
349            resultTo = null;
350            resultWho = null;
351            requestCode = 0;
352            callingPid = DEFAULT_CALLING_PID;
353            callingUid = DEFAULT_CALLING_UID;
354            callingPackage = null;
355            realCallingPid = 0;
356            realCallingUid = 0;
357            startFlags = 0;
358            activityOptions = null;
359            ignoreTargetSecurity = false;
360            componentSpecified = false;
361            outActivity = null;
362            inTask = null;
363            reason = null;
364            profilerInfo = null;
365            globalConfig = null;
366            userId = 0;
367            waitResult = null;
368            mayWait = false;
369            avoidMoveToFront = false;
370            allowPendingRemoteAnimationRegistryLookup = true;
371            filterCallingUid = UserHandle.USER_NULL;
372        }
373
374        /**
375         * Adopts all values from passed in request.
376         */
377        void set(Request request) {
378            caller = request.caller;
379            intent = request.intent;
380            ephemeralIntent = request.ephemeralIntent;
381            resolvedType = request.resolvedType;
382            activityInfo = request.activityInfo;
383            resolveInfo = request.resolveInfo;
384            voiceSession = request.voiceSession;
385            voiceInteractor = request.voiceInteractor;
386            resultTo = request.resultTo;
387            resultWho = request.resultWho;
388            requestCode = request.requestCode;
389            callingPid = request.callingPid;
390            callingUid = request.callingUid;
391            callingPackage = request.callingPackage;
392            realCallingPid = request.realCallingPid;
393            realCallingUid = request.realCallingUid;
394            startFlags = request.startFlags;
395            activityOptions = request.activityOptions;
396            ignoreTargetSecurity = request.ignoreTargetSecurity;
397            componentSpecified = request.componentSpecified;
398            outActivity = request.outActivity;
399            inTask = request.inTask;
400            reason = request.reason;
401            profilerInfo = request.profilerInfo;
402            globalConfig = request.globalConfig;
403            userId = request.userId;
404            waitResult = request.waitResult;
405            mayWait = request.mayWait;
406            avoidMoveToFront = request.avoidMoveToFront;
407            allowPendingRemoteAnimationRegistryLookup
408                    = request.allowPendingRemoteAnimationRegistryLookup;
409            filterCallingUid = request.filterCallingUid;
410        }
411    }
412
413    ActivityStarter(ActivityStartController controller, ActivityManagerService service,
414            ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
415        mController = controller;
416        mService = service;
417        mSupervisor = supervisor;
418        mInterceptor = interceptor;
419        reset(true);
420    }
421
422    /**
423     * Effectively duplicates the starter passed in. All state and request values will be
424     * mirrored.
425     * @param starter
426     */
427    void set(ActivityStarter starter) {
428        mStartActivity = starter.mStartActivity;
429        mIntent = starter.mIntent;
430        mCallingUid = starter.mCallingUid;
431        mOptions = starter.mOptions;
432
433        mLaunchTaskBehind = starter.mLaunchTaskBehind;
434        mLaunchFlags = starter.mLaunchFlags;
435        mLaunchMode = starter.mLaunchMode;
436
437        mLaunchParams.set(starter.mLaunchParams);
438
439        mNotTop = starter.mNotTop;
440        mDoResume = starter.mDoResume;
441        mStartFlags = starter.mStartFlags;
442        mSourceRecord = starter.mSourceRecord;
443        mPreferredDisplayId = starter.mPreferredDisplayId;
444
445        mInTask = starter.mInTask;
446        mAddingToTask = starter.mAddingToTask;
447        mReuseTask = starter.mReuseTask;
448
449        mNewTaskInfo = starter.mNewTaskInfo;
450        mNewTaskIntent = starter.mNewTaskIntent;
451        mSourceStack = starter.mSourceStack;
452
453        mTargetStack = starter.mTargetStack;
454        mMovedToFront = starter.mMovedToFront;
455        mNoAnimation = starter.mNoAnimation;
456        mKeepCurTransition = starter.mKeepCurTransition;
457        mAvoidMoveToFront = starter.mAvoidMoveToFront;
458
459        mVoiceSession = starter.mVoiceSession;
460        mVoiceInteractor = starter.mVoiceInteractor;
461
462        mIntentDelivered = starter.mIntentDelivered;
463
464        mRequest.set(starter.mRequest);
465    }
466
467    ActivityRecord getStartActivity() {
468        return mStartActivity;
469    }
470
471    boolean relatedToPackage(String packageName) {
472        return (mLastStartActivityRecord[0] != null
473                && packageName.equals(mLastStartActivityRecord[0].packageName))
474                || (mStartActivity != null && packageName.equals(mStartActivity.packageName));
475    }
476
477    /**
478     * Starts an activity based on the request parameters provided earlier.
479     * @return The starter result.
480     */
481    int execute() {
482        try {
483            // TODO(b/64750076): Look into passing request directly to these methods to allow
484            // for transactional diffs and preprocessing.
485            if (mRequest.mayWait) {
486                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
487                        mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
488                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
489                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
490                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
491                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
492                        mRequest.inTask, mRequest.reason,
493                        mRequest.allowPendingRemoteAnimationRegistryLookup);
494            } else {
495                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
496                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
497                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
498                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
499                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
500                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
501                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
502                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
503                        mRequest.allowPendingRemoteAnimationRegistryLookup);
504            }
505        } finally {
506            onExecutionComplete();
507        }
508    }
509
510    /**
511     * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
512     * Note that this method is called internally as well as part of {@link #startActivity}.
513     *
514     * @return The start result.
515     */
516    int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
517            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
518            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
519            ActivityRecord[] outActivity) {
520        try {
521            return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
522                    doResume, options, inTask, outActivity);
523        } finally {
524            onExecutionComplete();
525        }
526    }
527
528    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
529            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
530            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
531            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
532            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
533            SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
534            ActivityRecord[] outActivity, TaskRecord inTask, String reason,
535            boolean allowPendingRemoteAnimationRegistryLookup) {
536
537        if (TextUtils.isEmpty(reason)) {
538            throw new IllegalArgumentException("Need to specify a reason.");
539        }
540        mLastStartReason = reason;
541        mLastStartActivityTimeMs = System.currentTimeMillis();
542        mLastStartActivityRecord[0] = null;
543
544        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
545                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
546                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
547                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
548                inTask, allowPendingRemoteAnimationRegistryLookup);
549
550        if (outActivity != null) {
551            // mLastStartActivityRecord[0] is set in the call to startActivity above.
552            outActivity[0] = mLastStartActivityRecord[0];
553        }
554
555        return getExternalResult(mLastStartActivityResult);
556    }
557
558    static int getExternalResult(int result) {
559        // Aborted results are treated as successes externally, but we must track them internally.
560        return result != START_ABORTED ? result : START_SUCCESS;
561    }
562
563    /**
564     * Called when execution is complete. Sets state indicating completion and proceeds with
565     * recycling if appropriate.
566     */
567    private void onExecutionComplete() {
568        mController.onExecutionComplete(this);
569    }
570
571    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
572            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
573            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
574            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
575            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
576            SafeActivityOptions options,
577            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
578            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
579        int err = ActivityManager.START_SUCCESS;
580        // Pull the optional Ephemeral Installer-only bundle out of the options early.
581        final Bundle verificationBundle
582                = options != null ? options.popAppVerificationBundle() : null;
583
584        ProcessRecord callerApp = null;
585        if (caller != null) {
586            callerApp = mService.getRecordForAppLocked(caller);
587            if (callerApp != null) {
588                callingPid = callerApp.pid;
589                callingUid = callerApp.info.uid;
590            } else {
591                Slog.w(TAG, "Unable to find app for caller " + caller
592                        + " (pid=" + callingPid + ") when starting: "
593                        + intent.toString());
594                err = ActivityManager.START_PERMISSION_DENIED;
595            }
596        }
597
598        final int userId = aInfo != null && aInfo.applicationInfo != null
599                ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
600
601        if (err == ActivityManager.START_SUCCESS) {
602            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
603                    + "} from uid " + callingUid);
604        }
605
606        ActivityRecord sourceRecord = null;
607        ActivityRecord resultRecord = null;
608        if (resultTo != null) {
609            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
610            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
611                    "Will send result to " + resultTo + " " + sourceRecord);
612            if (sourceRecord != null) {
613                if (requestCode >= 0 && !sourceRecord.finishing) {
614                    resultRecord = sourceRecord;
615                }
616            }
617        }
618
619        final int launchFlags = intent.getFlags();
620
621        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
622            // Transfer the result target from the source activity to the new
623            // one being started, including any failures.
624            if (requestCode >= 0) {
625                SafeActivityOptions.abort(options);
626                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
627            }
628            resultRecord = sourceRecord.resultTo;
629            if (resultRecord != null && !resultRecord.isInStackLocked()) {
630                resultRecord = null;
631            }
632            resultWho = sourceRecord.resultWho;
633            requestCode = sourceRecord.requestCode;
634            sourceRecord.resultTo = null;
635            if (resultRecord != null) {
636                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
637            }
638            if (sourceRecord.launchedFromUid == callingUid) {
639                // The new activity is being launched from the same uid as the previous
640                // activity in the flow, and asking to forward its result back to the
641                // previous.  In this case the activity is serving as a trampoline between
642                // the two, so we also want to update its launchedFromPackage to be the
643                // same as the previous activity.  Note that this is safe, since we know
644                // these two packages come from the same uid; the caller could just as
645                // well have supplied that same package name itself.  This specifially
646                // deals with the case of an intent picker/chooser being launched in the app
647                // flow to redirect to an activity picked by the user, where we want the final
648                // activity to consider it to have been launched by the previous app activity.
649                callingPackage = sourceRecord.launchedFromPackage;
650            }
651        }
652
653        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
654            // We couldn't find a class that can handle the given Intent.
655            // That's the end of that!
656            err = ActivityManager.START_INTENT_NOT_RESOLVED;
657        }
658
659        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
660            // We couldn't find the specific class specified in the Intent.
661            // Also the end of the line.
662            err = ActivityManager.START_CLASS_NOT_FOUND;
663        }
664
665        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
666                && sourceRecord.getTask().voiceSession != null) {
667            // If this activity is being launched as part of a voice session, we need
668            // to ensure that it is safe to do so.  If the upcoming activity will also
669            // be part of the voice session, we can only launch it if it has explicitly
670            // said it supports the VOICE category, or it is a part of the calling app.
671            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
672                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
673                try {
674                    intent.addCategory(Intent.CATEGORY_VOICE);
675                    if (!mService.getPackageManager().activitySupportsIntent(
676                            intent.getComponent(), intent, resolvedType)) {
677                        Slog.w(TAG,
678                                "Activity being started in current voice task does not support voice: "
679                                        + intent);
680                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
681                    }
682                } catch (RemoteException e) {
683                    Slog.w(TAG, "Failure checking voice capabilities", e);
684                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
685                }
686            }
687        }
688
689        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
690            // If the caller is starting a new voice session, just make sure the target
691            // is actually allowing it to run this way.
692            try {
693                if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
694                        intent, resolvedType)) {
695                    Slog.w(TAG,
696                            "Activity being started in new voice task does not support: "
697                                    + intent);
698                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
699                }
700            } catch (RemoteException e) {
701                Slog.w(TAG, "Failure checking voice capabilities", e);
702                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
703            }
704        }
705
706        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
707
708        if (err != START_SUCCESS) {
709            if (resultRecord != null) {
710                resultStack.sendActivityResultLocked(
711                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
712            }
713            SafeActivityOptions.abort(options);
714            return err;
715        }
716
717        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
718                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
719                inTask != null, callerApp, resultRecord, resultStack);
720        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
721                callingPid, resolvedType, aInfo.applicationInfo);
722
723        // Merge the two options bundles, while realCallerOptions takes precedence.
724        ActivityOptions checkedOptions = options != null
725                ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
726                : null;
727        if (allowPendingRemoteAnimationRegistryLookup) {
728            checkedOptions = mService.getActivityStartController()
729                    .getPendingRemoteAnimationRegistry()
730                    .overrideOptionsIfNeeded(callingPackage, checkedOptions);
731        }
732        if (mService.mController != null) {
733            try {
734                // The Intent we give to the watcher has the extra data
735                // stripped off, since it can contain private information.
736                Intent watchIntent = intent.cloneFilter();
737                abort |= !mService.mController.activityStarting(watchIntent,
738                        aInfo.applicationInfo.packageName);
739            } catch (RemoteException e) {
740                mService.mController = null;
741            }
742        }
743
744        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
745        if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
746                callingUid, checkedOptions)) {
747            // activity start was intercepted, e.g. because the target user is currently in quiet
748            // mode (turn off work) or the target application is suspended
749            intent = mInterceptor.mIntent;
750            rInfo = mInterceptor.mRInfo;
751            aInfo = mInterceptor.mAInfo;
752            resolvedType = mInterceptor.mResolvedType;
753            inTask = mInterceptor.mInTask;
754            callingPid = mInterceptor.mCallingPid;
755            callingUid = mInterceptor.mCallingUid;
756            checkedOptions = mInterceptor.mActivityOptions;
757        }
758
759        if (abort) {
760            if (resultRecord != null) {
761                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
762                        RESULT_CANCELED, null);
763            }
764            // We pretend to the caller that it was really started, but
765            // they will just get a cancel result.
766            ActivityOptions.abort(checkedOptions);
767            return START_ABORTED;
768        }
769
770        // If permissions need a review before any of the app components can run, we
771        // launch the review activity and pass a pending intent to start the activity
772        // we are to launching now after the review is completed.
773        if (mService.mPermissionReviewRequired && aInfo != null) {
774            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
775                    aInfo.packageName, userId)) {
776                IIntentSender target = mService.getIntentSenderLocked(
777                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
778                        callingUid, userId, null, null, 0, new Intent[]{intent},
779                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
780                                | PendingIntent.FLAG_ONE_SHOT, null);
781
782                final int flags = intent.getFlags();
783                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
784                newIntent.setFlags(flags
785                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
786                newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
787                newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
788                if (resultRecord != null) {
789                    newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
790                }
791                intent = newIntent;
792
793                resolvedType = null;
794                callingUid = realCallingUid;
795                callingPid = realCallingPid;
796
797                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
798                        computeResolveFilterUid(
799                                callingUid, realCallingUid, mRequest.filterCallingUid));
800                aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
801                        null /*profilerInfo*/);
802
803                if (DEBUG_PERMISSIONS_REVIEW) {
804                    Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
805                            true, false) + "} from uid " + callingUid + " on display "
806                            + (mSupervisor.mFocusedStack == null
807                            ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
808                }
809            }
810        }
811
812        // If we have an ephemeral app, abort the process of launching the resolved intent.
813        // Instead, launch the ephemeral installer. Once the installer is finished, it
814        // starts either the intent we resolved here [on install error] or the ephemeral
815        // app [on install success].
816        if (rInfo != null && rInfo.auxiliaryInfo != null) {
817            intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
818                    callingPackage, verificationBundle, resolvedType, userId);
819            resolvedType = null;
820            callingUid = realCallingUid;
821            callingPid = realCallingPid;
822
823            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
824        }
825
826        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
827                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
828                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
829                mSupervisor, checkedOptions, sourceRecord);
830        if (outActivity != null) {
831            outActivity[0] = r;
832        }
833
834        if (r.appTimeTracker == null && sourceRecord != null) {
835            // If the caller didn't specify an explicit time tracker, we want to continue
836            // tracking under any it has.
837            r.appTimeTracker = sourceRecord.appTimeTracker;
838        }
839
840        final ActivityStack stack = mSupervisor.mFocusedStack;
841
842        // If we are starting an activity that is not from the same uid as the currently resumed
843        // one, check whether app switches are allowed.
844        if (voiceSession == null && (stack.getResumedActivity() == null
845                || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
846            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
847                    realCallingPid, realCallingUid, "Activity start")) {
848                mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
849                        sourceRecord, startFlags, stack, callerApp));
850                ActivityOptions.abort(checkedOptions);
851                return ActivityManager.START_SWITCHES_CANCELED;
852            }
853        }
854
855        if (mService.mDidAppSwitch) {
856            // This is the second allowed switch since we stopped switches,
857            // so now just generally allow switches.  Use case: user presses
858            // home (switches disabled, switch to home, mDidAppSwitch now true);
859            // user taps a home icon (coming from home so allowed, we hit here
860            // and now allow anyone to switch again).
861            mService.mAppSwitchesAllowedTime = 0;
862        } else {
863            mService.mDidAppSwitch = true;
864        }
865
866        mController.doPendingActivityLaunches(false);
867
868        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
869                true /* doResume */, checkedOptions, inTask, outActivity);
870    }
871
872
873    /**
874     * Creates a launch intent for the given auxiliary resolution data.
875     */
876    private @NonNull Intent createLaunchIntent(@Nullable AuxiliaryResolveInfo auxiliaryResponse,
877            Intent originalIntent, String callingPackage, Bundle verificationBundle,
878            String resolvedType, int userId) {
879        if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
880            // request phase two resolution
881            mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
882                    auxiliaryResponse, originalIntent, resolvedType, callingPackage,
883                    verificationBundle, userId);
884        }
885        return InstantAppResolver.buildEphemeralInstallerIntent(
886                originalIntent,
887                InstantAppResolver.sanitizeIntent(originalIntent),
888                auxiliaryResponse == null ? null : auxiliaryResponse.failureIntent,
889                callingPackage,
890                verificationBundle,
891                resolvedType,
892                userId,
893                auxiliaryResponse == null ? null : auxiliaryResponse.installFailureActivity,
894                auxiliaryResponse == null ? null : auxiliaryResponse.token,
895                auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo,
896                auxiliaryResponse == null ? null : auxiliaryResponse.filters);
897    }
898
899    void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
900        if (ActivityManager.isStartResultFatalError(result)) {
901            return;
902        }
903
904        // We're waiting for an activity launch to finish, but that activity simply
905        // brought another activity to front. We must also handle the case where the task is already
906        // in the front as a result of the trampoline activity being in the same task (it will be
907        // considered focused as the trampoline will be finished). Let startActivityMayWait() know
908        // about this, so it waits for the new activity to become visible instead.
909        mSupervisor.reportWaitingActivityLaunchedIfNeeded(r, result);
910
911        ActivityStack startedActivityStack = null;
912        final ActivityStack currentStack = r.getStack();
913        if (currentStack != null) {
914            startedActivityStack = currentStack;
915        } else if (mTargetStack != null) {
916            startedActivityStack = targetStack;
917        }
918
919        if (startedActivityStack == null) {
920            return;
921        }
922
923        final int clearTaskFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK;
924        boolean clearedTask = (mLaunchFlags & clearTaskFlags) == clearTaskFlags
925                && mReuseTask != null;
926        if (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP || clearedTask) {
927            // The activity was already running so it wasn't started, but either brought to the
928            // front or the new intent was delivered to it since it was already in front. Notify
929            // anyone interested in this piece of information.
930            switch (startedActivityStack.getWindowingMode()) {
931                case WINDOWING_MODE_PINNED:
932                    mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
933                            clearedTask);
934                    break;
935                case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
936                    final ActivityStack homeStack = mSupervisor.mHomeStack;
937                    if (homeStack != null && homeStack.shouldBeVisible(null /* starting */)) {
938                        mService.mWindowManager.showRecentApps();
939                    }
940                    break;
941            }
942        }
943    }
944
945    private int startActivityMayWait(IApplicationThread caller, int callingUid,
946            String callingPackage, Intent intent, String resolvedType,
947            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
948            IBinder resultTo, String resultWho, int requestCode, int startFlags,
949            ProfilerInfo profilerInfo, WaitResult outResult,
950            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
951            int userId, TaskRecord inTask, String reason,
952            boolean allowPendingRemoteAnimationRegistryLookup) {
953        // Refuse possible leaked file descriptors
954        if (intent != null && intent.hasFileDescriptors()) {
955            throw new IllegalArgumentException("File descriptors passed in Intent");
956        }
957        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
958        boolean componentSpecified = intent.getComponent() != null;
959
960        final int realCallingPid = Binder.getCallingPid();
961        final int realCallingUid = Binder.getCallingUid();
962
963        int callingPid;
964        if (callingUid >= 0) {
965            callingPid = -1;
966        } else if (caller == null) {
967            callingPid = realCallingPid;
968            callingUid = realCallingUid;
969        } else {
970            callingPid = callingUid = -1;
971        }
972
973        // Save a copy in case ephemeral needs it
974        final Intent ephemeralIntent = new Intent(intent);
975        // Don't modify the client's object!
976        intent = new Intent(intent);
977        if (componentSpecified
978                && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
979                && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
980                && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
981                && mService.getPackageManagerInternalLocked()
982                        .isInstantAppInstallerComponent(intent.getComponent())) {
983            // intercept intents targeted directly to the ephemeral installer the
984            // ephemeral installer should never be started with a raw Intent; instead
985            // adjust the intent so it looks like a "normal" instant app launch
986            intent.setComponent(null /*component*/);
987            componentSpecified = false;
988        }
989
990        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
991                0 /* matchFlags */,
992                        computeResolveFilterUid(
993                                callingUid, realCallingUid, mRequest.filterCallingUid));
994        if (rInfo == null) {
995            UserInfo userInfo = mSupervisor.getUserInfo(userId);
996            if (userInfo != null && userInfo.isManagedProfile()) {
997                // Special case for managed profiles, if attempting to launch non-cryto aware
998                // app in a locked managed profile from an unlocked parent allow it to resolve
999                // as user will be sent via confirm credentials to unlock the profile.
1000                UserManager userManager = UserManager.get(mService.mContext);
1001                boolean profileLockedAndParentUnlockingOrUnlocked = false;
1002                long token = Binder.clearCallingIdentity();
1003                try {
1004                    UserInfo parent = userManager.getProfileParent(userId);
1005                    profileLockedAndParentUnlockingOrUnlocked = (parent != null)
1006                            && userManager.isUserUnlockingOrUnlocked(parent.id)
1007                            && !userManager.isUserUnlockingOrUnlocked(userId);
1008                } finally {
1009                    Binder.restoreCallingIdentity(token);
1010                }
1011                if (profileLockedAndParentUnlockingOrUnlocked) {
1012                    rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
1013                            PackageManager.MATCH_DIRECT_BOOT_AWARE
1014                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1015                            computeResolveFilterUid(
1016                                    callingUid, realCallingUid, mRequest.filterCallingUid));
1017                }
1018            }
1019        }
1020        // Collect information about the target of the Intent.
1021        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
1022
1023        synchronized (mService) {
1024            final ActivityStack stack = mSupervisor.mFocusedStack;
1025            stack.mConfigWillChange = globalConfig != null
1026                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
1027            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1028                    "Starting activity when config will change = " + stack.mConfigWillChange);
1029
1030            final long origId = Binder.clearCallingIdentity();
1031
1032            if (aInfo != null &&
1033                    (aInfo.applicationInfo.privateFlags
1034                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 &&
1035                    mService.mHasHeavyWeightFeature) {
1036                // This may be a heavy-weight process!  Check to see if we already
1037                // have another, different heavy-weight process running.
1038                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
1039                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
1040                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
1041                            || !heavy.processName.equals(aInfo.processName))) {
1042                        int appCallingUid = callingUid;
1043                        if (caller != null) {
1044                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
1045                            if (callerApp != null) {
1046                                appCallingUid = callerApp.info.uid;
1047                            } else {
1048                                Slog.w(TAG, "Unable to find app for caller " + caller
1049                                        + " (pid=" + callingPid + ") when starting: "
1050                                        + intent.toString());
1051                                SafeActivityOptions.abort(options);
1052                                return ActivityManager.START_PERMISSION_DENIED;
1053                            }
1054                        }
1055
1056                        IIntentSender target = mService.getIntentSenderLocked(
1057                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
1058                                appCallingUid, userId, null, null, 0, new Intent[] { intent },
1059                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
1060                                        | PendingIntent.FLAG_ONE_SHOT, null);
1061
1062                        Intent newIntent = new Intent();
1063                        if (requestCode >= 0) {
1064                            // Caller is requesting a result.
1065                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
1066                        }
1067                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
1068                                new IntentSender(target));
1069                        if (heavy.activities.size() > 0) {
1070                            ActivityRecord hist = heavy.activities.get(0);
1071                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
1072                                    hist.packageName);
1073                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
1074                                    hist.getTask().taskId);
1075                        }
1076                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
1077                                aInfo.packageName);
1078                        newIntent.setFlags(intent.getFlags());
1079                        newIntent.setClassName("android",
1080                                HeavyWeightSwitcherActivity.class.getName());
1081                        intent = newIntent;
1082                        resolvedType = null;
1083                        caller = null;
1084                        callingUid = Binder.getCallingUid();
1085                        callingPid = Binder.getCallingPid();
1086                        componentSpecified = true;
1087                        rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
1088                                0 /* matchFlags */, computeResolveFilterUid(
1089                                        callingUid, realCallingUid, mRequest.filterCallingUid));
1090                        aInfo = rInfo != null ? rInfo.activityInfo : null;
1091                        if (aInfo != null) {
1092                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
1093                        }
1094                    }
1095                }
1096            }
1097
1098            final ActivityRecord[] outRecord = new ActivityRecord[1];
1099            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
1100                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
1101                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
1102                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
1103                    allowPendingRemoteAnimationRegistryLookup);
1104
1105            Binder.restoreCallingIdentity(origId);
1106
1107            if (stack.mConfigWillChange) {
1108                // If the caller also wants to switch to a new configuration,
1109                // do so now.  This allows a clean switch, as we are waiting
1110                // for the current activity to pause (so we will not destroy
1111                // it), and have not yet started the next activity.
1112                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
1113                        "updateConfiguration()");
1114                stack.mConfigWillChange = false;
1115                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1116                        "Updating to new configuration after starting activity.");
1117                mService.updateConfigurationLocked(globalConfig, null, false);
1118            }
1119
1120            if (outResult != null) {
1121                outResult.result = res;
1122
1123                final ActivityRecord r = outRecord[0];
1124
1125                switch(res) {
1126                    case START_SUCCESS: {
1127                        mSupervisor.mWaitingActivityLaunched.add(outResult);
1128                        do {
1129                            try {
1130                                mService.wait();
1131                            } catch (InterruptedException e) {
1132                            }
1133                        } while (outResult.result != START_TASK_TO_FRONT
1134                                && !outResult.timeout && outResult.who == null);
1135                        if (outResult.result == START_TASK_TO_FRONT) {
1136                            res = START_TASK_TO_FRONT;
1137                        }
1138                        break;
1139                    }
1140                    case START_DELIVERED_TO_TOP: {
1141                        outResult.timeout = false;
1142                        outResult.who = r.realActivity;
1143                        outResult.totalTime = 0;
1144                        outResult.thisTime = 0;
1145                        break;
1146                    }
1147                    case START_TASK_TO_FRONT: {
1148                        // ActivityRecord may represent a different activity, but it should not be
1149                        // in the resumed state.
1150                        if (r.nowVisible && r.isState(RESUMED)) {
1151                            outResult.timeout = false;
1152                            outResult.who = r.realActivity;
1153                            outResult.totalTime = 0;
1154                            outResult.thisTime = 0;
1155                        } else {
1156                            outResult.thisTime = SystemClock.uptimeMillis();
1157                            mSupervisor.waitActivityVisible(r.realActivity, outResult);
1158                            // Note: the timeout variable is not currently not ever set.
1159                            do {
1160                                try {
1161                                    mService.wait();
1162                                } catch (InterruptedException e) {
1163                                }
1164                            } while (!outResult.timeout && outResult.who == null);
1165                        }
1166                        break;
1167                    }
1168                }
1169            }
1170
1171            mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
1172            return res;
1173        }
1174    }
1175
1176    /**
1177     * Compute the logical UID based on which the package manager would filter
1178     * app components i.e. based on which the instant app policy would be applied
1179     * because it is the logical calling UID.
1180     *
1181     * @param customCallingUid The UID on whose behalf to make the call.
1182     * @param actualCallingUid The UID actually making the call.
1183     * @param filterCallingUid The UID to be used to filter for instant apps.
1184     * @return The logical UID making the call.
1185     */
1186    static int computeResolveFilterUid(int customCallingUid, int actualCallingUid,
1187            int filterCallingUid) {
1188        return filterCallingUid != UserHandle.USER_NULL
1189                ? filterCallingUid
1190                : (customCallingUid >= 0 ? customCallingUid : actualCallingUid);
1191    }
1192
1193    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
1194                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1195                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1196                ActivityRecord[] outActivity) {
1197        int result = START_CANCELED;
1198        try {
1199            mService.mWindowManager.deferSurfaceLayout();
1200            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
1201                    startFlags, doResume, options, inTask, outActivity);
1202        } finally {
1203            // If we are not able to proceed, disassociate the activity from the task. Leaving an
1204            // activity in an incomplete state can lead to issues, such as performing operations
1205            // without a window container.
1206            final ActivityStack stack = mStartActivity.getStack();
1207            if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
1208                stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
1209                        null /* intentResultData */, "startActivity", true /* oomAdj */);
1210            }
1211            mService.mWindowManager.continueSurfaceLayout();
1212        }
1213
1214        postStartActivityProcessing(r, result, mTargetStack);
1215
1216        return result;
1217    }
1218
1219    // Note: This method should only be called from {@link startActivity}.
1220    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1221            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1222            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1223            ActivityRecord[] outActivity) {
1224
1225        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1226                voiceInteractor);
1227
1228        computeLaunchingTaskFlags();
1229
1230        computeSourceStack();
1231
1232        mIntent.setFlags(mLaunchFlags);
1233
1234        ActivityRecord reusedActivity = getReusableIntentActivity();
1235
1236        int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1237        int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1238        if (mOptions != null) {
1239            preferredWindowingMode = mOptions.getLaunchWindowingMode();
1240            preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1241        }
1242
1243        // windowing mode and preferred launch display values from {@link LaunchParams} take
1244        // priority over those specified in {@link ActivityOptions}.
1245        if (!mLaunchParams.isEmpty()) {
1246            if (mLaunchParams.hasPreferredDisplay()) {
1247                preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
1248            }
1249
1250            if (mLaunchParams.hasWindowingMode()) {
1251                preferredWindowingMode = mLaunchParams.mWindowingMode;
1252            }
1253        }
1254
1255        if (reusedActivity != null) {
1256            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1257            // still needs to be a lock task mode violation since the task gets cleared out and
1258            // the device would otherwise leave the locked task.
1259            if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
1260                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1261                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1262                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1263                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1264            }
1265
1266            // True if we are clearing top and resetting of a standard (default) launch mode
1267            // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
1268            final boolean clearTopAndResetStandardLaunchMode =
1269                    (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
1270                            == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
1271                    && mLaunchMode == LAUNCH_MULTIPLE;
1272
1273            // If mStartActivity does not have a task associated with it, associate it with the
1274            // reused activity's task. Do not do so if we're clearing top and resetting for a
1275            // standard launchMode activity.
1276            if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
1277                mStartActivity.setTask(reusedActivity.getTask());
1278            }
1279
1280            if (reusedActivity.getTask().intent == null) {
1281                // This task was started because of movement of the activity based on affinity...
1282                // Now that we are actually launching it, we can assign the base intent.
1283                reusedActivity.getTask().setIntent(mStartActivity);
1284            }
1285
1286            // This code path leads to delivering a new intent, we want to make sure we schedule it
1287            // as the first operation, in case the activity will be resumed as a result of later
1288            // operations.
1289            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1290                    || isDocumentLaunchesIntoExisting(mLaunchFlags)
1291                    || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1292                final TaskRecord task = reusedActivity.getTask();
1293
1294                // In this situation we want to remove all activities from the task up to the one
1295                // being started. In most cases this means we are resetting the task to its initial
1296                // state.
1297                final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1298                        mLaunchFlags);
1299
1300                // The above code can remove {@code reusedActivity} from the task, leading to the
1301                // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1302                // task reference is needed in the call below to
1303                // {@link setTargetStackAndMoveToFrontIfNeeded}.
1304                if (reusedActivity.getTask() == null) {
1305                    reusedActivity.setTask(task);
1306                }
1307
1308                if (top != null) {
1309                    if (top.frontOfTask) {
1310                        // Activity aliases may mean we use different intents for the top activity,
1311                        // so make sure the task now has the identity of the new intent.
1312                        top.getTask().setIntent(mStartActivity);
1313                    }
1314                    deliverNewIntent(top);
1315                }
1316            }
1317
1318            mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
1319
1320            reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
1321
1322            final ActivityRecord outResult =
1323                    outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1324
1325            // When there is a reused activity and the current result is a trampoline activity,
1326            // set the reused activity as the result.
1327            if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1328                outActivity[0] = reusedActivity;
1329            }
1330
1331            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1332                // We don't need to start a new activity, and the client said not to do anything
1333                // if that is the case, so this is it!  And for paranoia, make sure we have
1334                // correctly resumed the top activity.
1335                resumeTargetStackIfNeeded();
1336                return START_RETURN_INTENT_TO_CALLER;
1337            }
1338
1339            if (reusedActivity != null) {
1340                setTaskFromIntentActivity(reusedActivity);
1341
1342                if (!mAddingToTask && mReuseTask == null) {
1343                    // We didn't do anything...  but it was needed (a.k.a., client don't use that
1344                    // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
1345
1346                    resumeTargetStackIfNeeded();
1347                    if (outActivity != null && outActivity.length > 0) {
1348                        outActivity[0] = reusedActivity;
1349                    }
1350
1351                    return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
1352                }
1353            }
1354        }
1355
1356        if (mStartActivity.packageName == null) {
1357            final ActivityStack sourceStack = mStartActivity.resultTo != null
1358                    ? mStartActivity.resultTo.getStack() : null;
1359            if (sourceStack != null) {
1360                sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1361                        mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1362                        null /* data */);
1363            }
1364            ActivityOptions.abort(mOptions);
1365            return START_CLASS_NOT_FOUND;
1366        }
1367
1368        // If the activity being launched is the same as the one currently at the top, then
1369        // we need to check if it should only be launched once.
1370        final ActivityStack topStack = mSupervisor.mFocusedStack;
1371        final ActivityRecord topFocused = topStack.getTopActivity();
1372        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1373        final boolean dontStart = top != null && mStartActivity.resultTo == null
1374                && top.realActivity.equals(mStartActivity.realActivity)
1375                && top.userId == mStartActivity.userId
1376                && top.app != null && top.app.thread != null
1377                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1378                || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
1379        if (dontStart) {
1380            // For paranoia, make sure we have correctly resumed the top activity.
1381            topStack.mLastPausedActivity = null;
1382            if (mDoResume) {
1383                mSupervisor.resumeFocusedStackTopActivityLocked();
1384            }
1385            ActivityOptions.abort(mOptions);
1386            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1387                // We don't need to start a new activity, and the client said not to do
1388                // anything if that is the case, so this is it!
1389                return START_RETURN_INTENT_TO_CALLER;
1390            }
1391
1392            deliverNewIntent(top);
1393
1394            // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1395            // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1396            mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
1397                    preferredLaunchDisplayId, topStack);
1398
1399            return START_DELIVERED_TO_TOP;
1400        }
1401
1402        boolean newTask = false;
1403        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1404                ? mSourceRecord.getTask() : null;
1405
1406        // Should this be considered a new task?
1407        int result = START_SUCCESS;
1408        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1409                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1410            newTask = true;
1411            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
1412        } else if (mSourceRecord != null) {
1413            result = setTaskFromSourceRecord();
1414        } else if (mInTask != null) {
1415            result = setTaskFromInTask();
1416        } else {
1417            // This not being started from an existing activity, and not part of a new task...
1418            // just put it in the top task, though these days this case should never happen.
1419            setTaskToCurrentTopOrCreateNewTask();
1420        }
1421        if (result != START_SUCCESS) {
1422            return result;
1423        }
1424
1425        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1426                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1427        mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1428                mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
1429        if (newTask) {
1430            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1431                    mStartActivity.getTask().taskId);
1432        }
1433        ActivityStack.logStartActivity(
1434                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
1435        mTargetStack.mLastPausedActivity = null;
1436
1437        mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
1438
1439        mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1440                mOptions);
1441        if (mDoResume) {
1442            final ActivityRecord topTaskActivity =
1443                    mStartActivity.getTask().topRunningActivityLocked();
1444            if (!mTargetStack.isFocusable()
1445                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1446                    && mStartActivity != topTaskActivity)) {
1447                // If the activity is not focusable, we can't resume it, but still would like to
1448                // make sure it becomes visible as it starts (this will also trigger entry
1449                // animation). An example of this are PIP activities.
1450                // Also, we don't want to resume activities in a task that currently has an overlay
1451                // as the starting activity just needs to be in the visible paused state until the
1452                // over is removed.
1453                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1454                // Go ahead and tell window manager to execute app transition for this activity
1455                // since the app transition will not be triggered through the resume channel.
1456                mService.mWindowManager.executeAppTransition();
1457            } else {
1458                // If the target stack was not previously focusable (previous top running activity
1459                // on that stack was not visible) then any prior calls to move the stack to the
1460                // will not update the focused stack.  If starting the new activity now allows the
1461                // task stack to be focusable, then ensure that we now update the focused stack
1462                // accordingly.
1463                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1464                    mTargetStack.moveToFront("startActivityUnchecked");
1465                }
1466                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1467                        mOptions);
1468            }
1469        } else if (mStartActivity != null) {
1470            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
1471        }
1472        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1473
1474        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
1475                preferredLaunchDisplayId, mTargetStack);
1476
1477        return START_SUCCESS;
1478    }
1479
1480    /**
1481     * Resets the {@link ActivityStarter} state.
1482     * @param clearRequest whether the request should be reset to default values.
1483     */
1484    void reset(boolean clearRequest) {
1485        mStartActivity = null;
1486        mIntent = null;
1487        mCallingUid = -1;
1488        mOptions = null;
1489
1490        mLaunchTaskBehind = false;
1491        mLaunchFlags = 0;
1492        mLaunchMode = INVALID_LAUNCH_MODE;
1493
1494        mLaunchParams.reset();
1495
1496        mNotTop = null;
1497        mDoResume = false;
1498        mStartFlags = 0;
1499        mSourceRecord = null;
1500        mPreferredDisplayId = INVALID_DISPLAY;
1501
1502        mInTask = null;
1503        mAddingToTask = false;
1504        mReuseTask = null;
1505
1506        mNewTaskInfo = null;
1507        mNewTaskIntent = null;
1508        mSourceStack = null;
1509
1510        mTargetStack = null;
1511        mMovedToFront = false;
1512        mNoAnimation = false;
1513        mKeepCurTransition = false;
1514        mAvoidMoveToFront = false;
1515
1516        mVoiceSession = null;
1517        mVoiceInteractor = null;
1518
1519        mIntentDelivered = false;
1520
1521        if (clearRequest) {
1522            mRequest.reset();
1523        }
1524    }
1525
1526    private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1527            boolean doResume, int startFlags, ActivityRecord sourceRecord,
1528            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1529        reset(false /* clearRequest */);
1530
1531        mStartActivity = r;
1532        mIntent = r.intent;
1533        mOptions = options;
1534        mCallingUid = r.launchedFromUid;
1535        mSourceRecord = sourceRecord;
1536        mVoiceSession = voiceSession;
1537        mVoiceInteractor = voiceInteractor;
1538
1539        mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
1540
1541        mLaunchParams.reset();
1542
1543        mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
1544                options, mLaunchParams);
1545
1546        mLaunchMode = r.launchMode;
1547
1548        mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1549                r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
1550                LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
1551        mLaunchTaskBehind = r.mLaunchTaskBehind
1552                && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
1553                && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1554
1555        sendNewTaskResultRequestIfNeeded();
1556
1557        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1558            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1559        }
1560
1561        // If we are actually going to launch in to a new task, there are some cases where
1562        // we further want to do multiple task.
1563        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1564            if (mLaunchTaskBehind
1565                    || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1566                mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1567            }
1568        }
1569
1570        // We'll invoke onUserLeaving before onPause only if the launching
1571        // activity did not explicitly state that this is an automated launch.
1572        mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1573        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1574                "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1575
1576        // If the caller has asked not to resume at this point, we make note
1577        // of this in the record so that we can skip it when trying to find
1578        // the top running activity.
1579        mDoResume = doResume;
1580        if (!doResume || !r.okToShowLocked()) {
1581            r.delayedResume = true;
1582            mDoResume = false;
1583        }
1584
1585        if (mOptions != null) {
1586            if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1587                r.mTaskOverlay = true;
1588                if (!mOptions.canTaskOverlayResume()) {
1589                    final TaskRecord task = mSupervisor.anyTaskForIdLocked(
1590                            mOptions.getLaunchTaskId());
1591                    final ActivityRecord top = task != null ? task.getTopActivity() : null;
1592                    if (top != null && !top.isState(RESUMED)) {
1593
1594                        // The caller specifies that we'd like to be avoided to be moved to the
1595                        // front, so be it!
1596                        mDoResume = false;
1597                        mAvoidMoveToFront = true;
1598                    }
1599                }
1600            } else if (mOptions.getAvoidMoveToFront()) {
1601                mDoResume = false;
1602                mAvoidMoveToFront = true;
1603            }
1604        }
1605
1606        mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1607
1608        mInTask = inTask;
1609        // In some flows in to this function, we retrieve the task record and hold on to it
1610        // without a lock before calling back in to here...  so the task at this point may
1611        // not actually be in recents.  Check for that, and if it isn't in recents just
1612        // consider it invalid.
1613        if (inTask != null && !inTask.inRecents) {
1614            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1615            mInTask = null;
1616        }
1617
1618        mStartFlags = startFlags;
1619        // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1620        // is the same as the one making the call...  or, as a special case, if we do not know
1621        // the caller then we count the current top activity as the caller.
1622        if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1623            ActivityRecord checkedCaller = sourceRecord;
1624            if (checkedCaller == null) {
1625                checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1626                        mNotTop);
1627            }
1628            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1629                // Caller is not the same as launcher, so always needed.
1630                mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1631            }
1632        }
1633
1634        mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1635    }
1636
1637    private void sendNewTaskResultRequestIfNeeded() {
1638        final ActivityStack sourceStack = mStartActivity.resultTo != null
1639                ? mStartActivity.resultTo.getStack() : null;
1640        if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1641            // For whatever reason this activity is being launched into a new task...
1642            // yet the caller has requested a result back.  Well, that is pretty messed up,
1643            // so instead immediately send back a cancel and let the new task continue launched
1644            // as normal without a dependency on its originator.
1645            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1646            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1647                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1648                    null /* data */);
1649            mStartActivity.resultTo = null;
1650        }
1651    }
1652
1653    private void computeLaunchingTaskFlags() {
1654        // If the caller is not coming from another activity, but has given us an explicit task into
1655        // which they would like us to launch the new activity, then let's see about doing that.
1656        if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
1657            final Intent baseIntent = mInTask.getBaseIntent();
1658            final ActivityRecord root = mInTask.getRootActivity();
1659            if (baseIntent == null) {
1660                ActivityOptions.abort(mOptions);
1661                throw new IllegalArgumentException("Launching into task without base intent: "
1662                        + mInTask);
1663            }
1664
1665            // If this task is empty, then we are adding the first activity -- it
1666            // determines the root, and must be launching as a NEW_TASK.
1667            if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1668                if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1669                    ActivityOptions.abort(mOptions);
1670                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1671                            + mStartActivity + " into different task " + mInTask);
1672                }
1673                if (root != null) {
1674                    ActivityOptions.abort(mOptions);
1675                    throw new IllegalArgumentException("Caller with mInTask " + mInTask
1676                            + " has root " + root + " but target is singleInstance/Task");
1677                }
1678            }
1679
1680            // If task is empty, then adopt the interesting intent launch flags in to the
1681            // activity being started.
1682            if (root == null) {
1683                final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1684                        | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1685                mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1686                        | (baseIntent.getFlags() & flagsOfInterest);
1687                mIntent.setFlags(mLaunchFlags);
1688                mInTask.setIntent(mStartActivity);
1689                mAddingToTask = true;
1690
1691                // If the task is not empty and the caller is asking to start it as the root of
1692                // a new task, then we don't actually want to start this on the task. We will
1693                // bring the task to the front, and possibly give it a new intent.
1694            } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1695                mAddingToTask = false;
1696
1697            } else {
1698                mAddingToTask = true;
1699            }
1700
1701            mReuseTask = mInTask;
1702        } else {
1703            mInTask = null;
1704            // Launch ResolverActivity in the source task, so that it stays in the task bounds
1705            // when in freeform workspace.
1706            // Also put noDisplay activities in the source task. These by itself can be placed
1707            // in any task/stack, however it could launch other activities like ResolverActivity,
1708            // and we want those to stay in the original task.
1709            if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1710                    && mSourceRecord.inFreeformWindowingMode())  {
1711                mAddingToTask = true;
1712            }
1713        }
1714
1715        if (mInTask == null) {
1716            if (mSourceRecord == null) {
1717                // This activity is not being started from another...  in this
1718                // case we -always- start a new task.
1719                if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1720                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1721                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1722                    mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1723                }
1724            } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1725                // The original activity who is starting us is running as a single
1726                // instance...  this new activity it is starting must go on its
1727                // own task.
1728                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1729            } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1730                // The activity being started is a single instance...  it always
1731                // gets launched into its own task.
1732                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1733            }
1734        }
1735    }
1736
1737    private void computeSourceStack() {
1738        if (mSourceRecord == null) {
1739            mSourceStack = null;
1740            return;
1741        }
1742        if (!mSourceRecord.finishing) {
1743            mSourceStack = mSourceRecord.getStack();
1744            return;
1745        }
1746
1747        // If the source is finishing, we can't further count it as our source. This is because the
1748        // task it is associated with may now be empty and on its way out, so we don't want to
1749        // blindly throw it in to that task.  Instead we will take the NEW_TASK flow and try to find
1750        // a task for it. But save the task information so it can be used when creating the new task.
1751        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1752            Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1753                    + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1754            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1755            mNewTaskInfo = mSourceRecord.info;
1756
1757            // It is not guaranteed that the source record will have a task associated with it. For,
1758            // example, if this method is being called for processing a pending activity launch, it
1759            // is possible that the activity has been removed from the task after the launch was
1760            // enqueued.
1761            final TaskRecord sourceTask = mSourceRecord.getTask();
1762            mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
1763        }
1764        mSourceRecord = null;
1765        mSourceStack = null;
1766    }
1767
1768    /**
1769     * Decide whether the new activity should be inserted into an existing task. Returns null
1770     * if not or an ActivityRecord with the task into which the new activity should be added.
1771     */
1772    private ActivityRecord getReusableIntentActivity() {
1773        // We may want to try to place the new activity in to an existing task.  We always
1774        // do this if the target activity is singleTask or singleInstance; we will also do
1775        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1776        // us to still place it in a new task: multi task, always doc mode, or being asked to
1777        // launch this as a new task behind the current one.
1778        boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1779                (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1780                || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
1781        // If bring to front is requested, and no result is requested and we have not been given
1782        // an explicit task to launch in to, and we can find a task that was started with this
1783        // same component, then instead of launching bring that one to the front.
1784        putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1785        ActivityRecord intentActivity = null;
1786        if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1787            final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1788            intentActivity = task != null ? task.getTopActivity() : null;
1789        } else if (putIntoExistingTask) {
1790            if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
1791                // There can be one and only one instance of single instance activity in the
1792                // history, and it is always in its own unique task, so we do a special search.
1793               intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1794                       mStartActivity.isActivityTypeHome());
1795            } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1796                // For the launch adjacent case we only want to put the activity in an existing
1797                // task if the activity already exists in the history.
1798                intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1799                        !(LAUNCH_SINGLE_TASK == mLaunchMode));
1800            } else {
1801                // Otherwise find the best task to put the activity in.
1802                intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
1803            }
1804        }
1805        return intentActivity;
1806    }
1807
1808    /**
1809     * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1810     * then return the Vr mode's virtual display ID. If not,  if the activity was started with
1811     * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
1812     * set, use that to launch the activity.
1813     */
1814    private int getPreferedDisplayId(
1815            ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
1816        // Check if the Activity is a VR activity. If so, the activity should be launched in
1817        // main display.
1818        if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1819            return DEFAULT_DISPLAY;
1820        }
1821
1822        // Get the virtual display id from ActivityManagerService.
1823        int displayId = mService.mVr2dDisplayId;
1824        if (displayId != INVALID_DISPLAY) {
1825            if (DEBUG_STACK) {
1826                Slog.d(TAG, "getSourceDisplayId :" + displayId);
1827            }
1828            return displayId;
1829        }
1830
1831        // If the caller requested a display, prefer that display.
1832        final int launchDisplayId =
1833                (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
1834        if (launchDisplayId != INVALID_DISPLAY) {
1835            return launchDisplayId;
1836        }
1837
1838        displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1839        // If the activity has a displayId set explicitly, launch it on the same displayId.
1840        if (displayId != INVALID_DISPLAY) {
1841            return displayId;
1842        }
1843        return DEFAULT_DISPLAY;
1844    }
1845
1846    /**
1847     * Figure out which task and activity to bring to front when we have found an existing matching
1848     * activity record in history. May also clear the task if needed.
1849     * @param intentActivity Existing matching activity.
1850     * @return {@link ActivityRecord} brought to front.
1851     */
1852    private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1853        mTargetStack = intentActivity.getStack();
1854        mTargetStack.mLastPausedActivity = null;
1855        // If the target task is not in the front, then we need to bring it to the front...
1856        // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1857        // the same behavior as if a new instance was being started, which means not bringing it
1858        // to the front if the caller is not itself in the front.
1859        final ActivityStack focusStack = mSupervisor.getFocusedStack();
1860        ActivityRecord curTop = (focusStack == null)
1861                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1862
1863        final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1864        if (topTask != null
1865                && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
1866                && !mAvoidMoveToFront) {
1867            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1868            if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
1869                    mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
1870                // We really do want to push this one into the user's face, right now.
1871                if (mLaunchTaskBehind && mSourceRecord != null) {
1872                    intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
1873                }
1874
1875                // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1876                // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1877                // So no point resuming any of the activities here, it just wastes one extra
1878                // resuming, plus enter AND exit transitions.
1879                // Here we only want to bring the target stack forward. Transition will be applied
1880                // to the new activity that's started after the old ones are gone.
1881                final boolean willClearTask =
1882                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1883                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1884                if (!willClearTask) {
1885                    final ActivityStack launchStack = getLaunchStack(
1886                            mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1887                    final TaskRecord intentTask = intentActivity.getTask();
1888                    if (launchStack == null || launchStack == mTargetStack) {
1889                        // We only want to move to the front, if we aren't going to launch on a
1890                        // different stack. If we launch on a different stack, we will put the
1891                        // task on top there.
1892                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1893                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1894                        mMovedToFront = true;
1895                    } else if (launchStack.inSplitScreenWindowingMode()) {
1896                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1897                            // If we want to launch adjacent and mTargetStack is not the computed
1898                            // launch stack - move task to top of computed stack.
1899                            intentTask.reparent(launchStack, ON_TOP,
1900                                    REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1901                                    "launchToSide");
1902                        } else {
1903                            // TODO: This should be reevaluated in MW v2.
1904                            // We choose to move task to front instead of launching it adjacent
1905                            // when specific stack was requested explicitly and it appeared to be
1906                            // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1907                            mTargetStack.moveTaskToFrontLocked(intentTask,
1908                                    mNoAnimation, mOptions, mStartActivity.appTimeTracker,
1909                                    "bringToFrontInsteadOfAdjacentLaunch");
1910                        }
1911                        mMovedToFront = launchStack != launchStack.getDisplay()
1912                                .getTopStackInWindowingMode(launchStack.getWindowingMode());
1913                    } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1914                        // Target and computed stacks are on different displays and we've
1915                        // found a matching task - move the existing instance to that display and
1916                        // move it to front.
1917                        intentActivity.getTask().reparent(launchStack, ON_TOP,
1918                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1919                                "reparentToDisplay");
1920                        mMovedToFront = true;
1921                    } else if (launchStack.isActivityTypeHome()
1922                            && !mTargetStack.isActivityTypeHome()) {
1923                        // It is possible for the home activity to be in another stack initially.
1924                        // For example, the activity may have been initially started with an intent
1925                        // which placed it in the fullscreen stack. To ensure the proper handling of
1926                        // the activity based on home stack assumptions, we must move it over.
1927                        intentActivity.getTask().reparent(launchStack, ON_TOP,
1928                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1929                                "reparentingHome");
1930                        mMovedToFront = true;
1931                    }
1932                    mOptions = null;
1933
1934                    // We are moving a task to the front, use starting window to hide initial drawn
1935                    // delay.
1936                    intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1937                            true /* taskSwitch */);
1938                }
1939            }
1940        }
1941        // Need to update mTargetStack because if task was moved out of it, the original stack may
1942        // be destroyed.
1943        mTargetStack = intentActivity.getStack();
1944        if (!mMovedToFront && mDoResume) {
1945            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1946                    + " from " + intentActivity);
1947            mTargetStack.moveToFront("intentActivityFound");
1948        }
1949
1950        mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
1951                WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
1952
1953        // If the caller has requested that the target task be reset, then do so.
1954        if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1955            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1956        }
1957        return intentActivity;
1958    }
1959
1960    private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1961        if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1962                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1963            // The caller has requested to completely replace any existing task with its new
1964            // activity. Well that should not be too hard...
1965            // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1966            // removed from calling performClearTaskLocked (For example, if it is being brought out
1967            // of history or if it is finished immediately), thus disassociating the task. Also note
1968            // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1969            // launching another activity.
1970            // TODO(b/36119896):  We shouldn't trigger activity launches in this path since we are
1971            // already launching one.
1972            final TaskRecord task = intentActivity.getTask();
1973            task.performClearTaskLocked();
1974            mReuseTask = task;
1975            mReuseTask.setIntent(mStartActivity);
1976        } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1977                || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1978            ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
1979                    mLaunchFlags);
1980            if (top == null) {
1981                // A special case: we need to start the activity because it is not currently
1982                // running, and the caller has asked to clear the current task to have this
1983                // activity at the top.
1984                mAddingToTask = true;
1985
1986                // We are no longer placing the activity in the task we previously thought we were.
1987                mStartActivity.setTask(null);
1988                // Now pretend like this activity is being started by the top of its task, so it
1989                // is put in the right place.
1990                mSourceRecord = intentActivity;
1991                final TaskRecord task = mSourceRecord.getTask();
1992                if (task != null && task.getStack() == null) {
1993                    // Target stack got cleared when we all activities were removed above.
1994                    // Go ahead and reset it.
1995                    mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1996                            mLaunchFlags, mOptions);
1997                    mTargetStack.addTask(task,
1998                            !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1999                }
2000            }
2001        } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
2002            // In this case the top activity on the task is the same as the one being launched,
2003            // so we take that as a request to bring the task to the foreground. If the top
2004            // activity in the task is the root activity, deliver this new intent to it if it
2005            // desires.
2006            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
2007                        || LAUNCH_SINGLE_TOP == mLaunchMode)
2008                    && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
2009                if (intentActivity.frontOfTask) {
2010                    intentActivity.getTask().setIntent(mStartActivity);
2011                }
2012                deliverNewIntent(intentActivity);
2013            } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
2014                // In this case we are launching the root activity of the task, but with a
2015                // different intent. We should start a new instance on top.
2016                mAddingToTask = true;
2017                mSourceRecord = intentActivity;
2018            }
2019        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
2020            // In this case an activity is being launched in to an existing task, without
2021            // resetting that task. This is typically the situation of launching an activity
2022            // from a notification or shortcut. We want to place the new activity on top of the
2023            // current task.
2024            mAddingToTask = true;
2025            mSourceRecord = intentActivity;
2026        } else if (!intentActivity.getTask().rootWasReset) {
2027            // In this case we are launching into an existing task that has not yet been started
2028            // from its front door. The current task has been brought to the front. Ideally,
2029            // we'd probably like to place this new task at the bottom of its stack, but that's
2030            // a little hard to do with the current organization of the code so for now we'll
2031            // just drop it.
2032            intentActivity.getTask().setIntent(mStartActivity);
2033        }
2034    }
2035
2036    private void resumeTargetStackIfNeeded() {
2037        if (mDoResume) {
2038            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
2039        } else {
2040            ActivityOptions.abort(mOptions);
2041        }
2042        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
2043    }
2044
2045    private int setTaskFromReuseOrCreateNewTask(
2046            TaskRecord taskToAffiliate, ActivityStack topStack) {
2047        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
2048
2049        // Do no move the target stack to front yet, as we might bail if
2050        // isLockTaskModeViolation fails below.
2051
2052        if (mReuseTask == null) {
2053            final TaskRecord task = mTargetStack.createTaskRecord(
2054                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
2055                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
2056                    mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
2057                    mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
2058                    mOptions);
2059            addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
2060            updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
2061
2062            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2063                    + " in new task " + mStartActivity.getTask());
2064        } else {
2065            addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
2066        }
2067
2068        if (taskToAffiliate != null) {
2069            mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
2070        }
2071
2072        if (mService.getLockTaskController().isLockTaskModeViolation(mStartActivity.getTask())) {
2073            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2074            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2075        }
2076
2077        if (mDoResume) {
2078            mTargetStack.moveToFront("reuseOrNewTask");
2079        }
2080        return START_SUCCESS;
2081    }
2082
2083    private void deliverNewIntent(ActivityRecord activity) {
2084        if (mIntentDelivered) {
2085            return;
2086        }
2087
2088        ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
2089        activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
2090                mStartActivity.launchedFromPackage);
2091        mIntentDelivered = true;
2092    }
2093
2094    private int setTaskFromSourceRecord() {
2095        if (mService.getLockTaskController().isLockTaskModeViolation(mSourceRecord.getTask())) {
2096            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2097            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2098        }
2099
2100        final TaskRecord sourceTask = mSourceRecord.getTask();
2101        final ActivityStack sourceStack = mSourceRecord.getStack();
2102        // We only want to allow changing stack in two cases:
2103        // 1. If the target task is not the top one. Otherwise we would move the launching task to
2104        //    the other side, rather than show two side by side.
2105        // 2. If activity is not allowed on target display.
2106        final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
2107                : sourceStack.mDisplayId;
2108        final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
2109                || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
2110        if (moveStackAllowed) {
2111            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
2112                    mOptions);
2113            // If target stack is not found now - we can't just rely on the source stack, as it may
2114            // be not suitable. Let's check other displays.
2115            if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
2116                // Can't use target display, lets find a stack on the source display.
2117                mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
2118                        sourceStack.mDisplayId, mStartActivity);
2119            }
2120            if (mTargetStack == null) {
2121                // There are no suitable stacks on the target and source display(s). Look on all
2122                // displays.
2123                mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
2124                        mStartActivity, -1 /* currentFocus */);
2125            }
2126        }
2127
2128        if (mTargetStack == null) {
2129            mTargetStack = sourceStack;
2130        } else if (mTargetStack != sourceStack) {
2131            sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
2132                    DEFER_RESUME, "launchToSide");
2133        }
2134
2135        final TaskRecord topTask = mTargetStack.topTask();
2136        if (topTask != sourceTask && !mAvoidMoveToFront) {
2137            mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
2138                    mStartActivity.appTimeTracker, "sourceTaskToFront");
2139        } else if (mDoResume) {
2140            mTargetStack.moveToFront("sourceStackToFront");
2141        }
2142
2143        if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2144            // In this case, we are adding the activity to an existing task, but the caller has
2145            // asked to clear that task if the activity is already running.
2146            ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
2147            mKeepCurTransition = true;
2148            if (top != null) {
2149                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
2150                deliverNewIntent(top);
2151                // For paranoia, make sure we have correctly resumed the top activity.
2152                mTargetStack.mLastPausedActivity = null;
2153                if (mDoResume) {
2154                    mSupervisor.resumeFocusedStackTopActivityLocked();
2155                }
2156                ActivityOptions.abort(mOptions);
2157                return START_DELIVERED_TO_TOP;
2158            }
2159        } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
2160            // In this case, we are launching an activity in our own task that may already be
2161            // running somewhere in the history, and we want to shuffle it to the front of the
2162            // stack if so.
2163            final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
2164            if (top != null) {
2165                final TaskRecord task = top.getTask();
2166                task.moveActivityToFrontLocked(top);
2167                top.updateOptionsLocked(mOptions);
2168                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
2169                deliverNewIntent(top);
2170                mTargetStack.mLastPausedActivity = null;
2171                if (mDoResume) {
2172                    mSupervisor.resumeFocusedStackTopActivityLocked();
2173                }
2174                return START_DELIVERED_TO_TOP;
2175            }
2176        }
2177
2178        // An existing activity is starting this new activity, so we want to keep the new one in
2179        // the same task as the one that is starting it.
2180        addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
2181        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2182                + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
2183        return START_SUCCESS;
2184    }
2185
2186    private int setTaskFromInTask() {
2187        // The caller is asking that the new activity be started in an explicit
2188        // task it has provided to us.
2189        if (mService.getLockTaskController().isLockTaskModeViolation(mInTask)) {
2190            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2191            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2192        }
2193
2194        mTargetStack = mInTask.getStack();
2195
2196        // Check whether we should actually launch the new activity in to the task,
2197        // or just reuse the current activity on top.
2198        ActivityRecord top = mInTask.getTopActivity();
2199        if (top != null && top.realActivity.equals(mStartActivity.realActivity)
2200                && top.userId == mStartActivity.userId) {
2201            if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
2202                    || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
2203                mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
2204                        mStartActivity.appTimeTracker, "inTaskToFront");
2205                if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
2206                    // We don't need to start a new activity, and the client said not to do
2207                    // anything if that is the case, so this is it!
2208                    return START_RETURN_INTENT_TO_CALLER;
2209                }
2210                deliverNewIntent(top);
2211                return START_DELIVERED_TO_TOP;
2212            }
2213        }
2214
2215        if (!mAddingToTask) {
2216            mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
2217                    mStartActivity.appTimeTracker, "inTaskToFront");
2218            // We don't actually want to have this activity added to the task, so just
2219            // stop here but still tell the caller that we consumed the intent.
2220            ActivityOptions.abort(mOptions);
2221            return START_TASK_TO_FRONT;
2222        }
2223
2224        if (!mLaunchParams.mBounds.isEmpty()) {
2225            // TODO: Shouldn't we already know what stack to use by the time we get here?
2226            ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
2227            if (stack != mInTask.getStack()) {
2228                mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
2229                        DEFER_RESUME, "inTaskToFront");
2230                mTargetStack = mInTask.getStack();
2231            }
2232
2233            updateBounds(mInTask, mLaunchParams.mBounds);
2234        }
2235
2236        mTargetStack.moveTaskToFrontLocked(
2237                mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
2238
2239        addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
2240        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2241                + " in explicit task " + mStartActivity.getTask());
2242
2243        return START_SUCCESS;
2244    }
2245
2246    @VisibleForTesting
2247    void updateBounds(TaskRecord task, Rect bounds) {
2248        if (bounds.isEmpty()) {
2249            return;
2250        }
2251
2252        final ActivityStack stack = task.getStack();
2253        if (stack != null && stack.resizeStackWithLaunchBounds()) {
2254            mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
2255        } else {
2256            task.updateOverrideConfiguration(bounds);
2257        }
2258    }
2259
2260    private void setTaskToCurrentTopOrCreateNewTask() {
2261        mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
2262        if (mDoResume) {
2263            mTargetStack.moveToFront("addingToTopTask");
2264        }
2265        final ActivityRecord prev = mTargetStack.getTopActivity();
2266        final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
2267                mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
2268                mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
2269        addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2270        mTargetStack.positionChildWindowContainerAtTop(task);
2271        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2272                + " in new guessed " + mStartActivity.getTask());
2273    }
2274
2275    private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
2276        if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
2277            parent.addActivityToTop(mStartActivity);
2278        } else {
2279            mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2280        }
2281    }
2282
2283    private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2284            boolean launchSingleTask, int launchFlags) {
2285        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2286                (launchSingleInstance || launchSingleTask)) {
2287            // We have a conflict between the Intent and the Activity manifest, manifest wins.
2288            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2289                    "\"singleInstance\" or \"singleTask\"");
2290            launchFlags &=
2291                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2292        } else {
2293            switch (r.info.documentLaunchMode) {
2294                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2295                    break;
2296                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2297                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2298                    break;
2299                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2300                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2301                    break;
2302                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2303                    launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2304                    break;
2305            }
2306        }
2307        return launchFlags;
2308    }
2309
2310    private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
2311            ActivityOptions aOptions) {
2312        final TaskRecord task = r.getTask();
2313        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
2314        if (stack != null) {
2315            return stack;
2316        }
2317
2318        final ActivityStack currentStack = task != null ? task.getStack() : null;
2319        if (currentStack != null) {
2320            if (mSupervisor.mFocusedStack != currentStack) {
2321                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2322                        "computeStackFocus: Setting " + "focused stack to r=" + r
2323                                + " task=" + task);
2324            } else {
2325                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2326                        "computeStackFocus: Focused stack already="
2327                                + mSupervisor.mFocusedStack);
2328            }
2329            return currentStack;
2330        }
2331
2332        if (canLaunchIntoFocusedStack(r, newTask)) {
2333            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2334                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2335            return mSupervisor.mFocusedStack;
2336        }
2337
2338        if (mPreferredDisplayId != DEFAULT_DISPLAY) {
2339            // Try to put the activity in a stack on a secondary display.
2340            stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
2341            if (stack == null) {
2342                // If source display is not suitable - look for topmost valid stack in the system.
2343                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2344                        "computeStackFocus: Can't launch on mPreferredDisplayId="
2345                                + mPreferredDisplayId + ", looking on all displays.");
2346                stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
2347            }
2348        }
2349        if (stack == null) {
2350            // We first try to put the task in the first dynamic stack on home display.
2351            final ActivityDisplay display = mSupervisor.getDefaultDisplay();
2352            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2353                stack = display.getChildAt(stackNdx);
2354                if (!stack.isOnHomeDisplay()) {
2355                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2356                            "computeStackFocus: Setting focused stack=" + stack);
2357                    return stack;
2358                }
2359            }
2360            // If there is no suitable dynamic stack then we figure out which static stack to use.
2361            stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
2362        }
2363        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2364                + r + " stackId=" + stack.mStackId);
2365        return stack;
2366    }
2367
2368    /** Check if provided activity record can launch in currently focused stack. */
2369    // TODO: This method can probably be consolidated into getLaunchStack() below.
2370    private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
2371        final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2372        final boolean canUseFocusedStack;
2373        if (focusedStack.isActivityTypeAssistant()) {
2374            canUseFocusedStack = r.isActivityTypeAssistant();
2375        } else {
2376            switch (focusedStack.getWindowingMode()) {
2377                case WINDOWING_MODE_FULLSCREEN:
2378                    // The fullscreen stack can contain any task regardless of if the task is
2379                    // resizeable or not. So, we let the task go in the fullscreen task if it is the
2380                    // focus stack.
2381                    canUseFocusedStack = true;
2382                    break;
2383                case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
2384                case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
2385                    // Any activity which supports split screen can go in the docked stack.
2386                    canUseFocusedStack = r.supportsSplitScreenWindowingMode();
2387                    break;
2388                case WINDOWING_MODE_FREEFORM:
2389                    // Any activity which supports freeform can go in the freeform stack.
2390                    canUseFocusedStack = r.supportsFreeform();
2391                    break;
2392                default:
2393                    // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2394                    // resizeable task.
2395                    canUseFocusedStack = !focusedStack.isOnHomeDisplay()
2396                            && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2397            }
2398        }
2399        return canUseFocusedStack && !newTask
2400                // Using the focus stack isn't important enough to override the preferred display.
2401                && (mPreferredDisplayId == focusedStack.mDisplayId);
2402    }
2403
2404    private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
2405            ActivityOptions aOptions) {
2406        // We are reusing a task, keep the stack!
2407        if (mReuseTask != null) {
2408            return mReuseTask.getStack();
2409        }
2410
2411        if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2412                 || mPreferredDisplayId != DEFAULT_DISPLAY) {
2413            // We don't pass in the default display id into the get launch stack call so it can do a
2414            // full resolution.
2415            final int candidateDisplay =
2416                    mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
2417            return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, candidateDisplay);
2418        }
2419        // Otherwise handle adjacent launch.
2420
2421        // The parent activity doesn't want to launch the activity on top of itself, but
2422        // instead tries to put it onto other side in side-by-side mode.
2423        final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
2424
2425        if (parentStack != mSupervisor.mFocusedStack) {
2426            // If task's parent stack is not focused - use it during adjacent launch.
2427            return parentStack;
2428        } else {
2429            if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2430                // If task is already on top of focused stack - use it. We don't want to move the
2431                // existing focused task to adjacent stack, just deliver new intent in this case.
2432                return mSupervisor.mFocusedStack;
2433            }
2434
2435            if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
2436                // If parent was in docked stack, the natural place to launch another activity
2437                // will be fullscreen, so it can appear alongside the docked window.
2438                final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
2439                return parentStack.getDisplay().getOrCreateStack(
2440                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
2441            } else {
2442                // If the parent is not in the docked stack, we check if there is docked window
2443                // and if yes, we will launch into that stack. If not, we just put the new
2444                // activity into parent's stack, because we can't find a better place.
2445                final ActivityStack dockedStack =
2446                        mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
2447                if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
2448                    // There is a docked stack, but it isn't visible, so we can't launch into that.
2449                    return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
2450                } else {
2451                    return dockedStack;
2452                }
2453            }
2454        }
2455    }
2456
2457    private boolean isLaunchModeOneOf(int mode1, int mode2) {
2458        return mode1 == mLaunchMode || mode2 == mLaunchMode;
2459    }
2460
2461    static boolean isDocumentLaunchesIntoExisting(int flags) {
2462        return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2463                (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2464    }
2465
2466    ActivityStarter setIntent(Intent intent) {
2467        mRequest.intent = intent;
2468        return this;
2469    }
2470
2471    @VisibleForTesting
2472    Intent getIntent() {
2473        return mRequest.intent;
2474    }
2475
2476    ActivityStarter setReason(String reason) {
2477        mRequest.reason = reason;
2478        return this;
2479    }
2480
2481    ActivityStarter setCaller(IApplicationThread caller) {
2482        mRequest.caller = caller;
2483        return this;
2484    }
2485
2486    ActivityStarter setEphemeralIntent(Intent intent) {
2487        mRequest.ephemeralIntent = intent;
2488        return this;
2489    }
2490
2491
2492    ActivityStarter setResolvedType(String type) {
2493        mRequest.resolvedType = type;
2494        return this;
2495    }
2496
2497    ActivityStarter setActivityInfo(ActivityInfo info) {
2498        mRequest.activityInfo = info;
2499        return this;
2500    }
2501
2502    ActivityStarter setResolveInfo(ResolveInfo info) {
2503        mRequest.resolveInfo = info;
2504        return this;
2505    }
2506
2507    ActivityStarter setVoiceSession(IVoiceInteractionSession voiceSession) {
2508        mRequest.voiceSession = voiceSession;
2509        return this;
2510    }
2511
2512    ActivityStarter setVoiceInteractor(IVoiceInteractor voiceInteractor) {
2513        mRequest.voiceInteractor = voiceInteractor;
2514        return this;
2515    }
2516
2517    ActivityStarter setResultTo(IBinder resultTo) {
2518        mRequest.resultTo = resultTo;
2519        return this;
2520    }
2521
2522    ActivityStarter setResultWho(String resultWho) {
2523        mRequest.resultWho = resultWho;
2524        return this;
2525    }
2526
2527    ActivityStarter setRequestCode(int requestCode) {
2528        mRequest.requestCode = requestCode;
2529        return this;
2530    }
2531
2532    ActivityStarter setCallingPid(int pid) {
2533        mRequest.callingPid = pid;
2534        return this;
2535    }
2536
2537    ActivityStarter setCallingUid(int uid) {
2538        mRequest.callingUid = uid;
2539        return this;
2540    }
2541
2542    ActivityStarter setCallingPackage(String callingPackage) {
2543        mRequest.callingPackage = callingPackage;
2544        return this;
2545    }
2546
2547    ActivityStarter setRealCallingPid(int pid) {
2548        mRequest.realCallingPid = pid;
2549        return this;
2550    }
2551
2552    ActivityStarter setRealCallingUid(int uid) {
2553        mRequest.realCallingUid = uid;
2554        return this;
2555    }
2556
2557    ActivityStarter setStartFlags(int startFlags) {
2558        mRequest.startFlags = startFlags;
2559        return this;
2560    }
2561
2562    ActivityStarter setActivityOptions(SafeActivityOptions options) {
2563        mRequest.activityOptions = options;
2564        return this;
2565    }
2566
2567    ActivityStarter setActivityOptions(Bundle bOptions) {
2568        return setActivityOptions(SafeActivityOptions.fromBundle(bOptions));
2569    }
2570
2571    ActivityStarter setIgnoreTargetSecurity(boolean ignoreTargetSecurity) {
2572        mRequest.ignoreTargetSecurity = ignoreTargetSecurity;
2573        return this;
2574    }
2575
2576    ActivityStarter setFilterCallingUid(int filterCallingUid) {
2577        mRequest.filterCallingUid = filterCallingUid;
2578        return this;
2579    }
2580
2581    ActivityStarter setComponentSpecified(boolean componentSpecified) {
2582        mRequest.componentSpecified = componentSpecified;
2583        return this;
2584    }
2585
2586    ActivityStarter setOutActivity(ActivityRecord[] outActivity) {
2587        mRequest.outActivity = outActivity;
2588        return this;
2589    }
2590
2591    ActivityStarter setInTask(TaskRecord inTask) {
2592        mRequest.inTask = inTask;
2593        return this;
2594    }
2595
2596    ActivityStarter setWaitResult(WaitResult result) {
2597        mRequest.waitResult = result;
2598        return this;
2599    }
2600
2601    ActivityStarter setProfilerInfo(ProfilerInfo info) {
2602        mRequest.profilerInfo = info;
2603        return this;
2604    }
2605
2606    ActivityStarter setGlobalConfiguration(Configuration config) {
2607        mRequest.globalConfig = config;
2608        return this;
2609    }
2610
2611    ActivityStarter setUserId(int userId) {
2612        mRequest.userId = userId;
2613        return this;
2614    }
2615
2616    ActivityStarter setMayWait(int userId) {
2617        mRequest.mayWait = true;
2618        mRequest.userId = userId;
2619
2620        return this;
2621    }
2622
2623    ActivityStarter setAllowPendingRemoteAnimationRegistryLookup(boolean allowLookup) {
2624        mRequest.allowPendingRemoteAnimationRegistryLookup = allowLookup;
2625        return this;
2626    }
2627
2628    void dump(PrintWriter pw, String prefix) {
2629        prefix = prefix + "  ";
2630        pw.print(prefix);
2631        pw.print("mCurrentUser=");
2632        pw.println(mSupervisor.mCurrentUser);
2633        pw.print(prefix);
2634        pw.print("mLastStartReason=");
2635        pw.println(mLastStartReason);
2636        pw.print(prefix);
2637        pw.print("mLastStartActivityTimeMs=");
2638        pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2639        pw.print(prefix);
2640        pw.print("mLastStartActivityResult=");
2641        pw.println(mLastStartActivityResult);
2642        ActivityRecord r = mLastStartActivityRecord[0];
2643        if (r != null) {
2644            pw.print(prefix);
2645            pw.println("mLastStartActivityRecord:");
2646            r.dump(pw, prefix + "  ");
2647        }
2648        if (mStartActivity != null) {
2649            pw.print(prefix);
2650            pw.println("mStartActivity:");
2651            mStartActivity.dump(pw, prefix + "  ");
2652        }
2653        if (mIntent != null) {
2654            pw.print(prefix);
2655            pw.print("mIntent=");
2656            pw.println(mIntent);
2657        }
2658        if (mOptions != null) {
2659            pw.print(prefix);
2660            pw.print("mOptions=");
2661            pw.println(mOptions);
2662        }
2663        pw.print(prefix);
2664        pw.print("mLaunchSingleTop=");
2665        pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
2666        pw.print(" mLaunchSingleInstance=");
2667        pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
2668        pw.print(" mLaunchSingleTask=");
2669        pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
2670        pw.print(prefix);
2671        pw.print("mLaunchFlags=0x");
2672        pw.print(Integer.toHexString(mLaunchFlags));
2673        pw.print(" mDoResume=");
2674        pw.print(mDoResume);
2675        pw.print(" mAddingToTask=");
2676        pw.println(mAddingToTask);
2677    }
2678}
2679