ActivityStarter.java revision dce2d161701f318ec71f8fe8de03031e1c4b0046
1package com.android.server.am;
2
3import static android.app.Activity.RESULT_CANCELED;
4import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
5import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
6import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
7import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
8import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
9import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
10import static android.app.ActivityManager.START_SUCCESS;
11import static android.app.ActivityManager.START_TASK_TO_FRONT;
12import static android.app.ActivityManager.StackId;
13import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
14import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
15import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
16import static android.app.ActivityManager.StackId.HOME_STACK_ID;
17import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
18import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
19import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
20import static android.app.PendingIntent.FLAG_IMMUTABLE;
21import static android.app.PendingIntent.FLAG_ONE_SHOT;
22import static android.content.Context.KEYGUARD_SERVICE;
23import static android.content.Intent.EXTRA_INTENT;
24import static android.content.Intent.EXTRA_PACKAGE_NAME;
25import static android.content.Intent.EXTRA_TASK_ID;
26import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
27import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
28import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
29import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE;
30import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
31import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
32import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
33import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
34import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
35import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
36import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
37import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
38import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
39import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
40import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
41import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
42import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
43import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
44import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
45import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
46import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
47import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
48import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
49import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
50import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
51import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
52import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
53import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
54import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
55import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
56import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
57import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
58import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
59import static com.android.server.am.ActivityManagerService.ANIMATE;
60import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
61import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
62import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
63import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
64import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
65import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
66import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
67import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
68
69import android.app.ActivityManager;
70import android.app.ActivityOptions;
71import android.app.AppGlobals;
72import android.app.IActivityContainer;
73import android.app.IActivityManager;
74import android.app.IApplicationThread;
75import android.app.KeyguardManager;
76import android.app.PendingIntent;
77import android.app.ProfilerInfo;
78import android.content.ComponentName;
79import android.content.IIntentSender;
80import android.content.Intent;
81import android.content.IntentSender;
82import android.content.pm.ActivityInfo;
83import android.content.pm.ApplicationInfo;
84import android.content.pm.ResolveInfo;
85import android.content.pm.UserInfo;
86import android.content.res.Configuration;
87import android.graphics.Rect;
88import android.os.Binder;
89import android.os.Build;
90import android.os.Bundle;
91import android.os.IBinder;
92import android.os.RemoteException;
93import android.os.SystemClock;
94import android.os.UserHandle;
95import android.os.UserManager;
96import android.service.voice.IVoiceInteractionSession;
97import android.util.EventLog;
98import android.util.Slog;
99import android.view.Display;
100
101import com.android.internal.app.HeavyWeightSwitcherActivity;
102import com.android.internal.app.IVoiceInteractor;
103import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
104import com.android.server.wm.WindowManagerService;
105
106import java.util.ArrayList;
107
108/**
109 * Controller for interpreting how and then launching activities.
110 *
111 * This class collects all the logic for determining how an intent and flags should be turned into
112 * an activity and associated task and stack.
113 */
114class ActivityStarter {
115    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
116    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
117    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
118    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
119    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
120
121    private final ActivityManagerService mService;
122    private final ActivityStackSupervisor mSupervisor;
123    private WindowManagerService mWindowManager;
124
125    final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
126
127    // Share state variable among methods when starting an activity.
128    private ActivityRecord mStartActivity;
129    private Intent mIntent;
130    private int mCallingUid;
131    private ActivityOptions mOptions;
132
133    private boolean mLaunchSingleTop;
134    private boolean mLaunchSingleInstance;
135    private boolean mLaunchSingleTask;
136    private boolean mLaunchTaskBehind;
137    private int mLaunchFlags;
138
139    private Rect mLaunchBounds;
140
141    private ActivityRecord mNotTop;
142    private boolean mDoResume;
143    private int mStartFlags;
144    private ActivityRecord mSourceRecord;
145
146    private TaskRecord mInTask;
147    private boolean mAddingToTask;
148    private TaskRecord mReuseTask;
149
150    private ActivityInfo mNewTaskInfo;
151    private Intent mNewTaskIntent;
152    private ActivityStack mSourceStack;
153    private ActivityStack mTargetStack;
154    // TODO: Is the mMoveHome flag really needed?
155    private boolean mMovedHome;
156    private boolean mMovedToFront;
157    private boolean mNoAnimation;
158    private boolean mKeepCurTransition;
159
160    private IVoiceInteractionSession mVoiceSession;
161    private IVoiceInteractor mVoiceInteractor;
162
163    private void reset() {
164        mStartActivity = null;
165        mIntent = null;
166        mCallingUid = -1;
167        mOptions = null;
168
169        mLaunchSingleTop = false;
170        mLaunchSingleInstance = false;
171        mLaunchSingleTask = false;
172        mLaunchTaskBehind = false;
173        mLaunchFlags = 0;
174
175        mLaunchBounds = null;
176
177        mNotTop = null;
178        mDoResume = false;
179        mStartFlags = 0;
180        mSourceRecord = null;
181
182        mInTask = null;
183        mAddingToTask = false;
184        mReuseTask = null;
185
186        mNewTaskInfo = null;
187        mNewTaskIntent = null;
188        mSourceStack = null;
189
190        mTargetStack = null;
191        mMovedHome = false;
192        mMovedToFront = false;
193        mNoAnimation = false;
194        mKeepCurTransition = false;
195
196        mVoiceSession = null;
197        mVoiceInteractor = null;
198    }
199
200    ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
201        mService = service;
202        mSupervisor = supervisor;
203    }
204
205    final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
206            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
207            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
208            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
209            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
210            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
211            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
212            TaskRecord inTask) {
213        int err = ActivityManager.START_SUCCESS;
214
215        ProcessRecord callerApp = null;
216        if (caller != null) {
217            callerApp = mService.getRecordForAppLocked(caller);
218            if (callerApp != null) {
219                callingPid = callerApp.pid;
220                callingUid = callerApp.info.uid;
221            } else {
222                Slog.w(TAG, "Unable to find app for caller " + caller
223                        + " (pid=" + callingPid + ") when starting: "
224                        + intent.toString());
225                err = ActivityManager.START_PERMISSION_DENIED;
226            }
227        }
228
229        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
230
231        if (err == ActivityManager.START_SUCCESS) {
232            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
233                    + "} from uid " + callingUid
234                    + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
235                    Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
236                    (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
237                            container.mActivityDisplay.mDisplayId)));
238        }
239
240        ActivityRecord sourceRecord = null;
241        ActivityRecord resultRecord = null;
242        if (resultTo != null) {
243            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
244            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
245                    "Will send result to " + resultTo + " " + sourceRecord);
246            if (sourceRecord != null) {
247                if (requestCode >= 0 && !sourceRecord.finishing) {
248                    resultRecord = sourceRecord;
249                }
250            }
251        }
252
253        final int launchFlags = intent.getFlags();
254
255        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
256            // Transfer the result target from the source activity to the new
257            // one being started, including any failures.
258            if (requestCode >= 0) {
259                ActivityOptions.abort(options);
260                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
261            }
262            resultRecord = sourceRecord.resultTo;
263            if (resultRecord != null && !resultRecord.isInStackLocked()) {
264                resultRecord = null;
265            }
266            resultWho = sourceRecord.resultWho;
267            requestCode = sourceRecord.requestCode;
268            sourceRecord.resultTo = null;
269            if (resultRecord != null) {
270                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
271            }
272            if (sourceRecord.launchedFromUid == callingUid) {
273                // The new activity is being launched from the same uid as the previous
274                // activity in the flow, and asking to forward its result back to the
275                // previous.  In this case the activity is serving as a trampoline between
276                // the two, so we also want to update its launchedFromPackage to be the
277                // same as the previous activity.  Note that this is safe, since we know
278                // these two packages come from the same uid; the caller could just as
279                // well have supplied that same package name itself.  This specifially
280                // deals with the case of an intent picker/chooser being launched in the app
281                // flow to redirect to an activity picked by the user, where we want the final
282                // activity to consider it to have been launched by the previous app activity.
283                callingPackage = sourceRecord.launchedFromPackage;
284            }
285        }
286
287        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
288            // We couldn't find a class that can handle the given Intent.
289            // That's the end of that!
290            err = ActivityManager.START_INTENT_NOT_RESOLVED;
291        }
292
293        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
294            // We couldn't find the specific class specified in the Intent.
295            // Also the end of the line.
296            err = ActivityManager.START_CLASS_NOT_FOUND;
297        }
298
299        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
300                && sourceRecord.task.voiceSession != null) {
301            // If this activity is being launched as part of a voice session, we need
302            // to ensure that it is safe to do so.  If the upcoming activity will also
303            // be part of the voice session, we can only launch it if it has explicitly
304            // said it supports the VOICE category, or it is a part of the calling app.
305            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
306                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
307                try {
308                    intent.addCategory(Intent.CATEGORY_VOICE);
309                    if (!AppGlobals.getPackageManager().activitySupportsIntent(
310                            intent.getComponent(), intent, resolvedType)) {
311                        Slog.w(TAG,
312                                "Activity being started in current voice task does not support voice: "
313                                        + intent);
314                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
315                    }
316                } catch (RemoteException e) {
317                    Slog.w(TAG, "Failure checking voice capabilities", e);
318                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
319                }
320            }
321        }
322
323        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
324            // If the caller is starting a new voice session, just make sure the target
325            // is actually allowing it to run this way.
326            try {
327                if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
328                        intent, resolvedType)) {
329                    Slog.w(TAG,
330                            "Activity being started in new voice task does not support: "
331                                    + intent);
332                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
333                }
334            } catch (RemoteException e) {
335                Slog.w(TAG, "Failure checking voice capabilities", e);
336                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
337            }
338        }
339
340        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
341
342        if (err != START_SUCCESS) {
343            if (resultRecord != null) {
344                resultStack.sendActivityResultLocked(
345                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
346            }
347            ActivityOptions.abort(options);
348            return err;
349        }
350
351        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
352                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
353                resultRecord, resultStack);
354        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
355                callingPid, resolvedType, aInfo.applicationInfo);
356
357        if (mService.mController != null) {
358            try {
359                // The Intent we give to the watcher has the extra data
360                // stripped off, since it can contain private information.
361                Intent watchIntent = intent.cloneFilter();
362                abort |= !mService.mController.activityStarting(watchIntent,
363                        aInfo.applicationInfo.packageName);
364            } catch (RemoteException e) {
365                mService.mController = null;
366            }
367        }
368
369        final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(intent,
370                resolvedType, aInfo, callingPackage, userId);
371        if (interceptingIntent != null) {
372            intent = interceptingIntent;
373            callingPid = realCallingPid;
374            callingUid = realCallingUid;
375            resolvedType = null;
376            // If we are intercepting and there was a task, convert it into an extra for the
377            // ConfirmCredentials intent and unassign it, as otherwise the task will move to
378            // front even if ConfirmCredentials is cancelled.
379            if (inTask != null) {
380                intent.putExtra(EXTRA_TASK_ID, inTask.taskId);
381                inTask = null;
382            }
383
384            final UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId);
385            rInfo = mSupervisor.resolveIntent(intent, resolvedType, parent.id);
386            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
387                    null /*profilerInfo*/);
388        }
389
390        if (abort) {
391            if (resultRecord != null) {
392                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
393                        RESULT_CANCELED, null);
394            }
395            // We pretend to the caller that it was really started, but
396            // they will just get a cancel result.
397            ActivityOptions.abort(options);
398            return START_SUCCESS;
399        }
400
401        // If permissions need a review before any of the app components can run, we
402        // launch the review activity and pass a pending intent to start the activity
403        // we are to launching now after the review is completed.
404        if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
405            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
406                    aInfo.packageName, userId)) {
407                IIntentSender target = mService.getIntentSenderLocked(
408                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
409                        callingUid, userId, null, null, 0, new Intent[]{intent},
410                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
411                                | PendingIntent.FLAG_ONE_SHOT, null);
412
413                final int flags = intent.getFlags();
414                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
415                newIntent.setFlags(flags
416                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
417                newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
418                newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
419                if (resultRecord != null) {
420                    newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
421                }
422                intent = newIntent;
423
424                resolvedType = null;
425                callingUid = realCallingUid;
426                callingPid = realCallingPid;
427
428                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
429                aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
430                        null /*profilerInfo*/);
431
432                if (DEBUG_PERMISSIONS_REVIEW) {
433                    Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
434                            true, false) + "} from uid " + callingUid + " on display "
435                            + (container == null ? (mSupervisor.mFocusedStack == null ?
436                            Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
437                            (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
438                                    container.mActivityDisplay.mDisplayId)));
439                }
440            }
441        }
442
443        // If we have an ephemeral app, abort the process of launching the resolved intent.
444        // Instead, launch the ephemeral installer. Once the installer is finished, it
445        // starts either the intent we resolved here [on install error] or the ephemeral
446        // app [on install success].
447        if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
448            // Create a pending intent to start the intent resolved here.
449            final IIntentSender failureTarget = mService.getIntentSenderLocked(
450                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
451                    Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
452                    new String[]{ resolvedType },
453                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
454                            | PendingIntent.FLAG_IMMUTABLE, null);
455
456            // Create a pending intent to start the ephemeral application; force it to be
457            // directed to the ephemeral package.
458            ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
459            final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
460                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
461                    Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
462                    new String[]{ resolvedType },
463                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
464                            | PendingIntent.FLAG_IMMUTABLE, null);
465
466            int flags = intent.getFlags();
467            intent = new Intent();
468            intent.setFlags(flags
469                    | Intent.FLAG_ACTIVITY_NEW_TASK
470                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
471            intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
472                    rInfo.ephemeralResolveInfo.getPackageName());
473            intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
474            intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
475
476            resolvedType = null;
477            callingUid = realCallingUid;
478            callingPid = realCallingPid;
479
480            rInfo = rInfo.ephemeralInstaller;
481            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
482        }
483
484        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
485                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
486                requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
487                options);
488        if (outActivity != null) {
489            outActivity[0] = r;
490        }
491
492        if (r.appTimeTracker == null && sourceRecord != null) {
493            // If the caller didn't specify an explicit time tracker, we want to continue
494            // tracking under any it has.
495            r.appTimeTracker = sourceRecord.appTimeTracker;
496        }
497
498        final ActivityStack stack = mSupervisor.mFocusedStack;
499        if (voiceSession == null && (stack.mResumedActivity == null
500                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
501            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
502                    realCallingPid, realCallingUid, "Activity start")) {
503                PendingActivityLaunch pal =  new PendingActivityLaunch(r,
504                        sourceRecord, startFlags, stack, callerApp);
505                mPendingActivityLaunches.add(pal);
506                ActivityOptions.abort(options);
507                return ActivityManager.START_SWITCHES_CANCELED;
508            }
509        }
510
511        if (mService.mDidAppSwitch) {
512            // This is the second allowed switch since we stopped switches,
513            // so now just generally allow switches.  Use case: user presses
514            // home (switches disabled, switch to home, mDidAppSwitch now true);
515            // user taps a home icon (coming from home so allowed, we hit here
516            // and now allow anyone to switch again).
517            mService.mAppSwitchesAllowedTime = 0;
518        } else {
519            mService.mDidAppSwitch = true;
520        }
521
522        doPendingActivityLaunchesLocked(false);
523
524        err = startActivityUnchecked(
525                r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);
526
527        if (err < 0) {
528            // If someone asked to have the keyguard dismissed on the next
529            // activity start, but we are not actually doing an activity
530            // switch...  just dismiss the keyguard now, because we
531            // probably want to see whatever is behind it.
532            mSupervisor.notifyActivityDrawnForKeyguard();
533        } else {
534            launchRecentsAppIfNeeded(stack);
535        }
536
537        return err;
538    }
539
540    /**
541     * Creates an intent to intercept the current activity start with Confirm Credentials if needed.
542     *
543     * @return The intercepting intent if needed.
544     */
545    private Intent interceptWithConfirmCredentialsIfNeeded(Intent intent, String resolvedType,
546            ActivityInfo aInfo, String callingPackage, int userId) {
547        if (!mService.mUserController.shouldConfirmCredentials(userId)) {
548            return null;
549        }
550        final IIntentSender target = mService.getIntentSenderLocked(
551                INTENT_SENDER_ACTIVITY, callingPackage,
552                Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
553                new String[]{ resolvedType },
554                FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE, null);
555        final int flags = intent.getFlags();
556        final KeyguardManager km = (KeyguardManager) mService.mContext
557                .getSystemService(KEYGUARD_SERVICE);
558        final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId);
559        if (newIntent == null) {
560            return null;
561        }
562        newIntent.setFlags(flags | FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
563        newIntent.putExtra(EXTRA_PACKAGE_NAME, aInfo.packageName);
564        newIntent.putExtra(EXTRA_INTENT, new IntentSender(target));
565        return newIntent;
566    }
567
568    void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
569        mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
570        startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
571                null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
572                null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
573                0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
574                0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
575                false /*ignoreTargetSecurity*/, false /*componentSpecified*/,  null /*outActivity*/,
576                null /*container*/, null /*inTask*/);
577        if (mSupervisor.inResumeTopActivity) {
578            // If we are in resume section already, home activity will be initialized, but not
579            // resumed (to avoid recursive resume) and will stay that way until something pokes it
580            // again. We need to schedule another resume.
581            mSupervisor.scheduleResumeTopActivities();
582        }
583    }
584
585    final int startActivityMayWait(IApplicationThread caller, int callingUid,
586            String callingPackage, Intent intent, String resolvedType,
587            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
588            IBinder resultTo, String resultWho, int requestCode, int startFlags,
589            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
590            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
591            IActivityContainer iContainer, TaskRecord inTask) {
592        // Refuse possible leaked file descriptors
593        if (intent != null && intent.hasFileDescriptors()) {
594            throw new IllegalArgumentException("File descriptors passed in Intent");
595        }
596        boolean componentSpecified = intent.getComponent() != null;
597
598        // Save a copy in case ephemeral needs it
599        final Intent ephemeralIntent = new Intent(intent);
600        // Don't modify the client's object!
601        intent = new Intent(intent);
602
603        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
604        // Collect information about the target of the Intent.
605        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
606
607        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
608        ActivityStackSupervisor.ActivityContainer container =
609                (ActivityStackSupervisor.ActivityContainer)iContainer;
610        synchronized (mService) {
611            if (container != null && container.mParentActivity != null &&
612                    container.mParentActivity.state != RESUMED) {
613                // Cannot start a child activity if the parent is not resumed.
614                return ActivityManager.START_CANCELED;
615            }
616            final int realCallingPid = Binder.getCallingPid();
617            final int realCallingUid = Binder.getCallingUid();
618            int callingPid;
619            if (callingUid >= 0) {
620                callingPid = -1;
621            } else if (caller == null) {
622                callingPid = realCallingPid;
623                callingUid = realCallingUid;
624            } else {
625                callingPid = callingUid = -1;
626            }
627
628            final ActivityStack stack;
629            if (container == null || container.mStack.isOnHomeDisplay()) {
630                stack = mSupervisor.mFocusedStack;
631            } else {
632                stack = container.mStack;
633            }
634            stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
635            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
636                    "Starting activity when config will change = " + stack.mConfigWillChange);
637
638            final long origId = Binder.clearCallingIdentity();
639
640            if (aInfo != null &&
641                    (aInfo.applicationInfo.privateFlags
642                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
643                // This may be a heavy-weight process!  Check to see if we already
644                // have another, different heavy-weight process running.
645                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
646                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
647                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
648                            || !heavy.processName.equals(aInfo.processName))) {
649                        int appCallingUid = callingUid;
650                        if (caller != null) {
651                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
652                            if (callerApp != null) {
653                                appCallingUid = callerApp.info.uid;
654                            } else {
655                                Slog.w(TAG, "Unable to find app for caller " + caller
656                                        + " (pid=" + callingPid + ") when starting: "
657                                        + intent.toString());
658                                ActivityOptions.abort(options);
659                                return ActivityManager.START_PERMISSION_DENIED;
660                            }
661                        }
662
663                        IIntentSender target = mService.getIntentSenderLocked(
664                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
665                                appCallingUid, userId, null, null, 0, new Intent[] { intent },
666                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
667                                        | PendingIntent.FLAG_ONE_SHOT, null);
668
669                        Intent newIntent = new Intent();
670                        if (requestCode >= 0) {
671                            // Caller is requesting a result.
672                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
673                        }
674                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
675                                new IntentSender(target));
676                        if (heavy.activities.size() > 0) {
677                            ActivityRecord hist = heavy.activities.get(0);
678                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
679                                    hist.packageName);
680                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
681                                    hist.task.taskId);
682                        }
683                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
684                                aInfo.packageName);
685                        newIntent.setFlags(intent.getFlags());
686                        newIntent.setClassName("android",
687                                HeavyWeightSwitcherActivity.class.getName());
688                        intent = newIntent;
689                        resolvedType = null;
690                        caller = null;
691                        callingUid = Binder.getCallingUid();
692                        callingPid = Binder.getCallingPid();
693                        componentSpecified = true;
694                        rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
695                        aInfo = rInfo != null ? rInfo.activityInfo : null;
696                        if (aInfo != null) {
697                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
698                        }
699                    }
700                }
701            }
702
703            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
704                    aInfo, rInfo, voiceSession, voiceInteractor,
705                    resultTo, resultWho, requestCode, callingPid,
706                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
707                    options, ignoreTargetSecurity, componentSpecified, null, container, inTask);
708
709            Binder.restoreCallingIdentity(origId);
710
711            if (stack.mConfigWillChange) {
712                // If the caller also wants to switch to a new configuration,
713                // do so now.  This allows a clean switch, as we are waiting
714                // for the current activity to pause (so we will not destroy
715                // it), and have not yet started the next activity.
716                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
717                        "updateConfiguration()");
718                stack.mConfigWillChange = false;
719                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
720                        "Updating to new configuration after starting activity.");
721                mService.updateConfigurationLocked(config, null, false);
722            }
723
724            if (outResult != null) {
725                outResult.result = res;
726                if (res == ActivityManager.START_SUCCESS) {
727                    mSupervisor.mWaitingActivityLaunched.add(outResult);
728                    do {
729                        try {
730                            mService.wait();
731                        } catch (InterruptedException e) {
732                        }
733                    } while (!outResult.timeout && outResult.who == null);
734                } else if (res == START_TASK_TO_FRONT) {
735                    ActivityRecord r = stack.topRunningActivityLocked();
736                    if (r.nowVisible && r.state == RESUMED) {
737                        outResult.timeout = false;
738                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
739                        outResult.totalTime = 0;
740                        outResult.thisTime = 0;
741                    } else {
742                        outResult.thisTime = SystemClock.uptimeMillis();
743                        mSupervisor.mWaitingActivityVisible.add(outResult);
744                        do {
745                            try {
746                                mService.wait();
747                            } catch (InterruptedException e) {
748                            }
749                        } while (!outResult.timeout && outResult.who == null);
750                    }
751                }
752            }
753
754            return res;
755        }
756    }
757
758    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
759            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
760            Bundle bOptions, int userId) {
761        if (intents == null) {
762            throw new NullPointerException("intents is null");
763        }
764        if (resolvedTypes == null) {
765            throw new NullPointerException("resolvedTypes is null");
766        }
767        if (intents.length != resolvedTypes.length) {
768            throw new IllegalArgumentException("intents are length different than resolvedTypes");
769        }
770
771
772        int callingPid;
773        if (callingUid >= 0) {
774            callingPid = -1;
775        } else if (caller == null) {
776            callingPid = Binder.getCallingPid();
777            callingUid = Binder.getCallingUid();
778        } else {
779            callingPid = callingUid = -1;
780        }
781        final long origId = Binder.clearCallingIdentity();
782        try {
783            synchronized (mService) {
784                ActivityRecord[] outActivity = new ActivityRecord[1];
785                for (int i=0; i<intents.length; i++) {
786                    Intent intent = intents[i];
787                    if (intent == null) {
788                        continue;
789                    }
790
791                    // Refuse possible leaked file descriptors
792                    if (intent != null && intent.hasFileDescriptors()) {
793                        throw new IllegalArgumentException("File descriptors passed in Intent");
794                    }
795
796                    boolean componentSpecified = intent.getComponent() != null;
797
798                    // Don't modify the client's object!
799                    intent = new Intent(intent);
800
801                    // Collect information about the target of the Intent.
802                    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
803                            null, userId);
804                    // TODO: New, check if this is correct
805                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
806
807                    if (aInfo != null &&
808                            (aInfo.applicationInfo.privateFlags
809                                    & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
810                        throw new IllegalArgumentException(
811                                "FLAG_CANT_SAVE_STATE not supported here");
812                    }
813
814                    ActivityOptions options = ActivityOptions.fromBundle(
815                            i == intents.length - 1 ? bOptions : null);
816                    int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
817                            resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
818                            callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
819                            options, false, componentSpecified, outActivity, null, null);
820                    if (res < 0) {
821                        return res;
822                    }
823
824                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
825                }
826            }
827        } finally {
828            Binder.restoreCallingIdentity(origId);
829        }
830
831        return START_SUCCESS;
832    }
833
834    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
835            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
836            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
837
838        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
839                voiceInteractor);
840
841        computeLaunchingTaskFlags();
842
843        computeSourceStack();
844
845        mIntent.setFlags(mLaunchFlags);
846
847        ActivityRecord intentActivity = getReusableIntentActivity();
848
849        if (intentActivity != null) {
850            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
851            // still needs to be a lock task mode violation since the task gets cleared out and
852            // the device would otherwise leave the locked task.
853            if (mSupervisor.isLockTaskModeViolation(intentActivity.task,
854                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
855                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
856                mSupervisor.showLockTaskToast();
857                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
858                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
859            }
860
861            if (mStartActivity.task == null) {
862                mStartActivity.task = intentActivity.task;
863            }
864            if (intentActivity.task.intent == null) {
865                // This task was started because of movement of the activity based on affinity...
866                // Now that we are actually launching it, we can assign the base intent.
867                intentActivity.task.setIntent(mStartActivity);
868            }
869
870            // This code path leads to delivering a new intent, we want to make sure we schedule it
871            // as the first operation, in case the activity will be resumed as a result of later
872            // operations.
873            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
874                    || mLaunchSingleInstance || mLaunchSingleTask) {
875                // In this situation we want to remove all activities from the task up to the one
876                // being started. In most cases this means we are resetting the task to its initial
877                // state.
878                final ActivityRecord top = intentActivity.task.performClearTaskLocked(
879                        mStartActivity, mLaunchFlags);
880                if (top != null) {
881                    if (top.frontOfTask) {
882                        // Activity aliases may mean we use different intents for the top activity,
883                        // so make sure the task now has the identity of the new intent.
884                        top.task.setIntent(mStartActivity);
885                    }
886                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
887                    top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
888                            mStartActivity.launchedFromPackage);
889                }
890            }
891
892            intentActivity = setTargetStackAndMoveToFrontIfNeeded(intentActivity);
893
894            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
895                // We don't need to start a new activity, and the client said not to do anything
896                // if that is the case, so this is it!  And for paranoia, make sure we have
897                // correctly resumed the top activity.
898                resumeTargetStackIfNeeded();
899                return START_RETURN_INTENT_TO_CALLER;
900            }
901
902            setTaskFromIntentActivity(intentActivity);
903
904            if (!mAddingToTask && mReuseTask == null) {
905                // We didn't do anything...  but it was needed (a.k.a., client don't use that
906                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
907                resumeTargetStackIfNeeded();
908                return START_TASK_TO_FRONT;
909            }
910        }
911
912        if (mStartActivity.packageName == null) {
913            if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
914                mStartActivity.resultTo.task.stack.sendActivityResultLocked(
915                        -1, mStartActivity.resultTo, mStartActivity.resultWho,
916                        mStartActivity.requestCode, RESULT_CANCELED, null);
917            }
918            ActivityOptions.abort(mOptions);
919            return START_CLASS_NOT_FOUND;
920        }
921
922        // If the activity being launched is the same as the one currently at the top, then
923        // we need to check if it should only be launched once.
924        final ActivityStack topStack = mSupervisor.mFocusedStack;
925        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
926        final boolean dontStart = top != null && mStartActivity.resultTo == null
927                && top.realActivity.equals(mStartActivity.realActivity)
928                && top.userId == mStartActivity.userId
929                && top.app != null && top.app.thread != null
930                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
931                || mLaunchSingleTop || mLaunchSingleTask);
932        if (dontStart) {
933            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
934            // For paranoia, make sure we have correctly resumed the top activity.
935            topStack.mLastPausedActivity = null;
936            if (mDoResume) {
937                mSupervisor.resumeFocusedStackTopActivityLocked();
938            }
939            ActivityOptions.abort(mOptions);
940            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
941                // We don't need to start a new activity, and the client said not to do
942                // anything if that is the case, so this is it!
943                return START_RETURN_INTENT_TO_CALLER;
944            }
945            top.deliverNewIntentLocked(
946                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
947            return START_DELIVERED_TO_TOP;
948        }
949
950        boolean newTask = false;
951        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
952                ? mSourceRecord.task : null;
953
954        // Should this be considered a new task?
955        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
956                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
957            newTask = true;
958            setTaskFromReuseOrCreateNewTask(taskToAffiliate);
959
960            if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
961                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
962                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
963            }
964            if (!mMovedHome
965                    && (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
966                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
967                // Caller wants to appear on home activity, so before starting
968                // their own activity we will bring home to the front.
969                mStartActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
970            }
971        } else if (mSourceRecord != null) {
972            if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
973                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
974                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
975            }
976
977            final int result = setTaskFromSourceRecord();
978            if (result != START_SUCCESS) {
979                return result;
980            }
981        } else if (mInTask != null) {
982            // The caller is asking that the new activity be started in an explicit
983            // task it has provided to us.
984            if (mSupervisor.isLockTaskModeViolation(mInTask)) {
985                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
986                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
987            }
988
989            final int result = setTaskFromInTask();
990            if (result != START_SUCCESS) {
991                return result;
992            }
993        } else {
994            // This not being started from an existing activity, and not part of a new task...
995            // just put it in the top task, though these days this case should never happen.
996            setTaskToCurrentTopOrCreateNewTask();
997        }
998
999        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1000                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1001
1002        if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1003            mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1004        }
1005        if (newTask) {
1006            EventLog.writeEvent(
1007                    EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1008        }
1009        ActivityStack.logStartActivity(
1010                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1011        mTargetStack.mLastPausedActivity = null;
1012        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1013        if (mDoResume) {
1014            if (!mLaunchTaskBehind) {
1015                // TODO(b/26381750): Remove this code after verification that all the decision
1016                // points above moved targetStack to the front which will also set the focus
1017                // activity.
1018                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1019            }
1020            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1021                    mOptions);
1022        } else {
1023            mTargetStack.addRecentActivityLocked(mStartActivity);
1024        }
1025        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1026
1027        if (!mStartActivity.task.mResizeable
1028                && mSupervisor.isStackDockedInEffect(mTargetStack.mStackId)) {
1029            mSupervisor.showNonResizeableDockToast(mStartActivity.task.taskId);
1030        }
1031
1032        return START_SUCCESS;
1033    }
1034
1035    private void launchRecentsAppIfNeeded(ActivityStack topStack) {
1036        if (topStack.mStackId == HOME_STACK_ID && mTargetStack.mStackId == DOCKED_STACK_ID) {
1037            // We launch an activity while being in home stack, which means either launcher or
1038            // recents into docked stack. We don't want the launched activity to be alone in a
1039            // docked stack, so we want to immediately launch recents too.
1040            if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
1041            mWindowManager.showRecentApps();
1042        }
1043    }
1044
1045    private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1046            boolean doResume, int startFlags, ActivityRecord sourceRecord,
1047            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1048        reset();
1049
1050        mStartActivity = r;
1051        mIntent = r.intent;
1052        mOptions = options;
1053        mCallingUid = r.launchedFromUid;
1054        mSourceRecord = sourceRecord;
1055        mVoiceSession = voiceSession;
1056        mVoiceInteractor = voiceInteractor;
1057
1058        mLaunchBounds = getOverrideBounds(r, options, inTask);
1059
1060        mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1061        mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1062        mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1063        mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1064                r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1065        mLaunchTaskBehind = r.mLaunchTaskBehind
1066                && !mLaunchSingleTask && !mLaunchSingleInstance
1067                && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1068
1069        sendNewTaskResultRequestIfNeeded();
1070
1071        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1072            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1073        }
1074
1075        // If we are actually going to launch in to a new task, there are some cases where
1076        // we further want to do multiple task.
1077        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1078            if (mLaunchTaskBehind
1079                    || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1080                mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1081            }
1082        }
1083
1084        // We'll invoke onUserLeaving before onPause only if the launching
1085        // activity did not explicitly state that this is an automated launch.
1086        mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1087        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1088                "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1089
1090        // If the caller has asked not to resume at this point, we make note
1091        // of this in the record so that we can skip it when trying to find
1092        // the top running activity.
1093        mDoResume = doResume;
1094        if (!doResume || !mSupervisor.okToShowLocked(r)) {
1095            r.delayedResume = true;
1096            mDoResume = false;
1097        }
1098
1099        mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1100
1101        mInTask = inTask;
1102        // In some flows in to this function, we retrieve the task record and hold on to it
1103        // without a lock before calling back in to here...  so the task at this point may
1104        // not actually be in recents.  Check for that, and if it isn't in recents just
1105        // consider it invalid.
1106        if (inTask != null && !inTask.inRecents) {
1107            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1108            mInTask = null;
1109        }
1110
1111        mStartFlags = startFlags;
1112        // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1113        // is the same as the one making the call...  or, as a special case, if we do not know
1114        // the caller then we count the current top activity as the caller.
1115        if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1116            ActivityRecord checkedCaller = sourceRecord;
1117            if (checkedCaller == null) {
1118                checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1119                        mNotTop);
1120            }
1121            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1122                // Caller is not the same as launcher, so always needed.
1123                mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1124            }
1125        }
1126
1127        mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1128    }
1129
1130    private void sendNewTaskResultRequestIfNeeded() {
1131        if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1132                && mStartActivity.resultTo.task.stack != null) {
1133            // For whatever reason this activity is being launched into a new task...
1134            // yet the caller has requested a result back.  Well, that is pretty messed up,
1135            // so instead immediately send back a cancel and let the new task continue launched
1136            // as normal without a dependency on its originator.
1137            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1138            mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1139                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1140            mStartActivity.resultTo = null;
1141        }
1142    }
1143
1144    private void computeLaunchingTaskFlags() {
1145        // If the caller is not coming from another activity, but has given us an explicit task into
1146        // which they would like us to launch the new activity, then let's see about doing that.
1147        if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1148            final Intent baseIntent = mInTask.getBaseIntent();
1149            final ActivityRecord root = mInTask.getRootActivity();
1150            if (baseIntent == null) {
1151                ActivityOptions.abort(mOptions);
1152                throw new IllegalArgumentException("Launching into task without base intent: "
1153                        + mInTask);
1154            }
1155
1156            // If this task is empty, then we are adding the first activity -- it
1157            // determines the root, and must be launching as a NEW_TASK.
1158            if (mLaunchSingleInstance || mLaunchSingleTask) {
1159                if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1160                    ActivityOptions.abort(mOptions);
1161                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1162                            + mStartActivity + " into different task " + mInTask);
1163                }
1164                if (root != null) {
1165                    ActivityOptions.abort(mOptions);
1166                    throw new IllegalArgumentException("Caller with mInTask " + mInTask
1167                            + " has root " + root + " but target is singleInstance/Task");
1168                }
1169            }
1170
1171            // If task is empty, then adopt the interesting intent launch flags in to the
1172            // activity being started.
1173            if (root == null) {
1174                final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1175                        | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1176                mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1177                        | (baseIntent.getFlags() & flagsOfInterest);
1178                mIntent.setFlags(mLaunchFlags);
1179                mInTask.setIntent(mStartActivity);
1180                mAddingToTask = true;
1181
1182                // If the task is not empty and the caller is asking to start it as the root of
1183                // a new task, then we don't actually want to start this on the task. We will
1184                // bring the task to the front, and possibly give it a new intent.
1185            } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1186                mAddingToTask = false;
1187
1188            } else {
1189                mAddingToTask = true;
1190            }
1191
1192            mReuseTask = mInTask;
1193        } else {
1194            mInTask = null;
1195            // Launch ResolverActivity in the source task, so that it stays in the task bounds
1196            // when in freeform workspace.
1197            // Also put noDisplay activities in the source task. These by itself can be placed
1198            // in any task/stack, however it could launch other activities like ResolverActivity,
1199            // and we want those to stay in the original task.
1200            if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1201                    && mSourceRecord.isFreeform())  {
1202                mAddingToTask = true;
1203            }
1204        }
1205
1206        if (mInTask == null) {
1207            if (mSourceRecord == null) {
1208                // This activity is not being started from another...  in this
1209                // case we -always- start a new task.
1210                if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1211                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1212                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1213                    mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1214                }
1215            } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1216                // The original activity who is starting us is running as a single
1217                // instance...  this new activity it is starting must go on its
1218                // own task.
1219                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1220            } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1221                // The activity being started is a single instance...  it always
1222                // gets launched into its own task.
1223                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1224            }
1225        }
1226    }
1227
1228    private void computeSourceStack() {
1229        if (mSourceRecord == null) {
1230            mSourceStack = null;
1231            return;
1232        }
1233        if (!mSourceRecord.finishing) {
1234            mSourceStack = mSourceRecord.task.stack;
1235            return;
1236        }
1237
1238        // If the source is finishing, we can't further count it as our source. This is because the
1239        // task it is associated with may now be empty and on its way out, so we don't want to
1240        // blindly throw it in to that task.  Instead we will take the NEW_TASK flow and try to find
1241        // a task for it. But save the task information so it can be used when creating the new task.
1242        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1243            Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1244                    + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1245            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1246            mNewTaskInfo = mSourceRecord.info;
1247            mNewTaskIntent = mSourceRecord.task.intent;
1248        }
1249        mSourceRecord = null;
1250        mSourceStack = null;
1251    }
1252
1253    /**
1254     * Decide whether the new activity should be inserted into an existing task. Returns null
1255     * if not or an ActivityRecord with the task into which the new activity should be added.
1256     */
1257    private ActivityRecord getReusableIntentActivity() {
1258        // We may want to try to place the new activity in to an existing task.  We always
1259        // do this if the target activity is singleTask or singleInstance; we will also do
1260        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1261        // us to still place it in a new task: multi task, always doc mode, or being asked to
1262        // launch this as a new task behind the current one.
1263        boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1264                (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1265                || mLaunchSingleInstance || mLaunchSingleTask;
1266        // If bring to front is requested, and no result is requested and we have not been given
1267        // an explicit task to launch in to, and we can find a task that was started with this
1268        // same component, then instead of launching bring that one to the front.
1269        putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1270        ActivityRecord intentActivity = null;
1271        if (putIntoExistingTask) {
1272            // See if there is a task to bring to the front.  If this is a SINGLE_INSTANCE
1273            // activity, there can be one and only one instance of it in the history, and it is
1274            // always in its own unique task, so we do a special search.
1275            intentActivity = mLaunchSingleInstance ? mSupervisor.findActivityLocked(mIntent, mStartActivity.info)
1276                    : mSupervisor.findTaskLocked(mStartActivity);
1277        }
1278        return intentActivity;
1279    }
1280
1281    private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1282        mTargetStack = intentActivity.task.stack;
1283        mTargetStack.mLastPausedActivity = null;
1284        // If the target task is not in the front, then we need to bring it to the front...
1285        // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1286        // the same behavior as if a new instance was being started, which means not bringing it
1287        // to the front if the caller is not itself in the front.
1288        final ActivityStack focusStack = mSupervisor.getFocusedStack();
1289        ActivityRecord curTop = (focusStack == null)
1290                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1291
1292        if (curTop != null && (curTop.task != intentActivity.task ||
1293                curTop.task != focusStack.topTask())) {
1294            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1295            if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1296                    mSourceStack.topActivity().task == mSourceRecord.task)) {
1297                // We really do want to push this one into the user's face, right now.
1298                if (mLaunchTaskBehind && mSourceRecord != null) {
1299                    intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1300                }
1301                mMovedHome = true;
1302                final ActivityStack launchStack =
1303                        getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1304                                mOptions, true);
1305                if (launchStack == null || launchStack == mTargetStack) {
1306                    // We only want to move to the front, if we aren't going to launch on a
1307                    // different stack. If we launch on a different stack, we will put the
1308                    // task on top there.
1309                    mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1310                            mOptions, mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1311                    mMovedToFront = true;
1312                }
1313                if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1314                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1315                    // Caller wants to appear on home activity.
1316                    intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1317                }
1318                mOptions = null;
1319            }
1320        }
1321        if (!mMovedToFront && mDoResume) {
1322            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1323                    + " from " + intentActivity);
1324            mTargetStack.moveToFront("intentActivityFound");
1325        }
1326
1327        // If the caller has requested that the target task be reset, then do so.
1328        if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1329            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1330        }
1331        return intentActivity;
1332    }
1333
1334    private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1335        if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1336                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1337            // The caller has requested to completely replace any existing task with its new
1338            // activity. Well that should not be too hard...
1339            mReuseTask = intentActivity.task;
1340            mReuseTask.performClearTaskLocked();
1341            mReuseTask.setIntent(mStartActivity);
1342        } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1343                || mLaunchSingleInstance || mLaunchSingleTask) {
1344            ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1345                    mLaunchFlags);
1346            if (top == null) {
1347                // A special case: we need to start the activity because it is not currently
1348                // running, and the caller has asked to clear the current task to have this
1349                // activity at the top.
1350                mAddingToTask = true;
1351                // Now pretend like this activity is being started by the top of its task, so it
1352                // is put in the right place.
1353                mSourceRecord = intentActivity;
1354                final TaskRecord task = mSourceRecord.task;
1355                if (task != null && task.stack == null) {
1356                    // Target stack got cleared when we all activities were removed above.
1357                    // Go ahead and reset it.
1358                    mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1359                            null /* bounds */, mLaunchFlags, mOptions);
1360                    mTargetStack.addTask(task,
1361                            !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1362                }
1363            }
1364        } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1365            // In this case the top activity on the task is the same as the one being launched,
1366            // so we take that as a request to bring the task to the foreground. If the top
1367            // activity in the task is the root activity, deliver this new intent to it if it
1368            // desires.
1369            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1370                    && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1371                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1372                        intentActivity.task);
1373                if (intentActivity.frontOfTask) {
1374                    intentActivity.task.setIntent(mStartActivity);
1375                }
1376                intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1377                        mStartActivity.launchedFromPackage);
1378            } else if (!mStartActivity.intent.filterEquals(intentActivity.task.intent)) {
1379                // In this case we are launching the root activity of the task, but with a
1380                // different intent. We should start a new instance on top.
1381                mAddingToTask = true;
1382                mSourceRecord = intentActivity;
1383            }
1384        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1385            // In this case an activity is being launched in to an existing task, without
1386            // resetting that task. This is typically the situation of launching an activity
1387            // from a notification or shortcut. We want to place the new activity on top of the
1388            // current task.
1389            mAddingToTask = true;
1390            mSourceRecord = intentActivity;
1391        } else if (!intentActivity.task.rootWasReset) {
1392            // In this case we are launching into an existing task that has not yet been started
1393            // from its front door. The current task has been brought to the front. Ideally,
1394            // we'd probably like to place this new task at the bottom of its stack, but that's
1395            // a little hard to do with the current organization of the code so for now we'll
1396            // just drop it.
1397            intentActivity.task.setIntent(mStartActivity);
1398        }
1399    }
1400
1401    private void resumeTargetStackIfNeeded() {
1402        if (mDoResume) {
1403            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1404            if (!mMovedToFront) {
1405                // Make sure to notify Keyguard as well if we are not running an app transition
1406                // later.
1407                mSupervisor.notifyActivityDrawnForKeyguard();
1408            }
1409        } else {
1410            ActivityOptions.abort(mOptions);
1411        }
1412        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1413    }
1414
1415    private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1416        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1417                mOptions);
1418        if (mDoResume) {
1419            mTargetStack.moveToFront("startingNewTask");
1420        }
1421
1422        if (mReuseTask == null) {
1423            final TaskRecord task = mTargetStack.createTaskRecord(mSupervisor.getNextTaskId(),
1424                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1425                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1426                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1427            mStartActivity.setTask(task, taskToAffiliate);
1428            if (mLaunchBounds != null) {
1429                mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1430            }
1431            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1432                    "Starting new activity " +
1433                            mStartActivity + " in new task " + mStartActivity.task);
1434        } else {
1435            mStartActivity.setTask(mReuseTask, taskToAffiliate);
1436        }
1437    }
1438
1439    private int setTaskFromSourceRecord() {
1440        final TaskRecord sourceTask = mSourceRecord.task;
1441        // We only want to allow changing stack if the target task is not the top one,
1442        // otherwise we would move the launching task to the other side, rather than show
1443        // two side by side.
1444        final boolean launchToSideAllowed = sourceTask.stack.topTask() != sourceTask;
1445        mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, launchToSideAllowed);
1446
1447        if (mTargetStack == null) {
1448            mTargetStack = sourceTask.stack;
1449        } else if (mTargetStack != sourceTask.stack) {
1450            mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1451                    ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1452        }
1453        if (mDoResume) {
1454            mTargetStack.moveToFront("sourceStackToFront");
1455        }
1456        final TaskRecord topTask = mTargetStack.topTask();
1457        if (topTask != sourceTask) {
1458            mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1459                    mStartActivity.appTimeTracker, "sourceTaskToFront");
1460        }
1461        if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1462            // In this case, we are adding the activity to an existing task, but the caller has
1463            // asked to clear that task if the activity is already running.
1464            ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1465            mKeepCurTransition = true;
1466            if (top != null) {
1467                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1468                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1469                // For paranoia, make sure we have correctly resumed the top activity.
1470                mTargetStack.mLastPausedActivity = null;
1471                if (mDoResume) {
1472                    mSupervisor.resumeFocusedStackTopActivityLocked();
1473                }
1474                ActivityOptions.abort(mOptions);
1475                return START_DELIVERED_TO_TOP;
1476            }
1477        } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1478            // In this case, we are launching an activity in our own task that may already be
1479            // running somewhere in the history, and we want to shuffle it to the front of the
1480            // stack if so.
1481            final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1482            if (top != null) {
1483                final TaskRecord task = top.task;
1484                task.moveActivityToFrontLocked(top);
1485                top.updateOptionsLocked(mOptions);
1486                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1487                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1488                mTargetStack.mLastPausedActivity = null;
1489                if (mDoResume) {
1490                    mSupervisor.resumeFocusedStackTopActivityLocked();
1491                }
1492                return START_DELIVERED_TO_TOP;
1493            }
1494        }
1495
1496        // An existing activity is starting this new activity, so we want to keep the new one in
1497        // the same task as the one that is starting it.
1498        mStartActivity.setTask(sourceTask, null);
1499        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1500                + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1501        return START_SUCCESS;
1502    }
1503
1504    private int setTaskFromInTask() {
1505        if (mLaunchBounds != null) {
1506            mInTask.updateOverrideConfiguration(mLaunchBounds);
1507            int stackId = mInTask.getLaunchStackId();
1508            if (stackId != mInTask.stack.mStackId) {
1509                mSupervisor.moveTaskToStackUncheckedLocked(
1510                        mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1511            }
1512        }
1513        mTargetStack = mInTask.stack;
1514        mTargetStack.moveTaskToFrontLocked(
1515                mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1516
1517        // Check whether we should actually launch the new activity in to the task,
1518        // or just reuse the current activity on top.
1519        ActivityRecord top = mInTask.getTopActivity();
1520        if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1521            if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1522                    || mLaunchSingleTop || mLaunchSingleTask) {
1523                ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1524                if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1525                    // We don't need to start a new activity, and the client said not to do
1526                    // anything if that is the case, so this is it!
1527                    return START_RETURN_INTENT_TO_CALLER;
1528                }
1529                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1530                return START_DELIVERED_TO_TOP;
1531            }
1532        }
1533
1534        if (!mAddingToTask) {
1535            // We don't actually want to have this activity added to the task, so just
1536            // stop here but still tell the caller that we consumed the intent.
1537            ActivityOptions.abort(mOptions);
1538            return START_TASK_TO_FRONT;
1539        }
1540
1541        mStartActivity.setTask(mInTask, null);
1542        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1543                "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1544
1545        return START_SUCCESS;
1546    }
1547
1548    private void setTaskToCurrentTopOrCreateNewTask() {
1549        mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1550                mOptions);
1551        if (mDoResume) {
1552            mTargetStack.moveToFront("addingToTopTask");
1553        }
1554        final ActivityRecord prev = mTargetStack.topActivity();
1555        final TaskRecord task = prev != null ? prev.task
1556                : mTargetStack.createTaskRecord(
1557                mSupervisor.getNextTaskId(), mStartActivity.info, mIntent, null, null, true);
1558        mStartActivity.setTask(task, null);
1559        mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1560        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1561                "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1562    }
1563
1564    private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1565            boolean launchSingleTask, int launchFlags) {
1566        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1567                (launchSingleInstance || launchSingleTask)) {
1568            // We have a conflict between the Intent and the Activity manifest, manifest wins.
1569            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1570                    "\"singleInstance\" or \"singleTask\"");
1571            launchFlags &=
1572                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1573        } else {
1574            switch (r.info.documentLaunchMode) {
1575                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1576                    break;
1577                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1578                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1579                    break;
1580                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1581                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1582                    break;
1583                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1584                    launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1585                    break;
1586            }
1587        }
1588        return launchFlags;
1589    }
1590
1591    final void doPendingActivityLaunchesLocked(boolean doResume) {
1592        while (!mPendingActivityLaunches.isEmpty()) {
1593            PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1594
1595            try {
1596                startActivityUnchecked(pal.r, pal.sourceRecord, null, null, pal.startFlags,
1597                        doResume && mPendingActivityLaunches.isEmpty(), null, null);
1598            } catch (Exception e) {
1599                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1600                pal.sendErrorResult(e.getMessage());
1601            }
1602        }
1603    }
1604
1605    private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1606            int launchFlags, ActivityOptions aOptions) {
1607        final TaskRecord task = r.task;
1608        if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1609            return mSupervisor.mHomeStack;
1610        }
1611
1612        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions, true);
1613        if (stack != null) {
1614            return stack;
1615        }
1616
1617        if (task != null && task.stack != null) {
1618            stack = task.stack;
1619            if (stack.isOnHomeDisplay()) {
1620                if (mSupervisor.mFocusedStack != stack) {
1621                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1622                            "computeStackFocus: Setting " + "focused stack to r=" + r
1623                                    + " task=" + task);
1624                } else {
1625                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1626                            "computeStackFocus: Focused stack already="
1627                                    + mSupervisor.mFocusedStack);
1628                }
1629            }
1630            return stack;
1631        }
1632
1633        final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1634        if (container != null) {
1635            // The first time put it on the desired stack, after this put on task stack.
1636            r.mInitialActivityContainer = null;
1637            return container.mStack;
1638        }
1639
1640        // The fullscreen stack can contain any task regardless of if the task is resizeable
1641        // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1642        // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1643        // we can also put it in the focused stack.
1644        final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1645        final boolean canUseFocusedStack =
1646                focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1647                        || focusedStackId == DOCKED_STACK_ID
1648                        || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeable());
1649        if (canUseFocusedStack && (!newTask
1650                || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1651            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1652                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1653            return mSupervisor.mFocusedStack;
1654        }
1655
1656        // We first try to put the task in the first dynamic stack.
1657        final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1658        for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1659            stack = homeDisplayStacks.get(stackNdx);
1660            if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1661                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1662                        "computeStackFocus: Setting focused stack=" + stack);
1663                return stack;
1664            }
1665        }
1666
1667        // If there is no suitable dynamic stack then we figure out which static stack to use.
1668        final int stackId = task != null ? task.getLaunchStackId() :
1669                bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1670                        FULLSCREEN_WORKSPACE_STACK_ID;
1671        stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1672        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1673                + r + " stackId=" + stack.mStackId);
1674        return stack;
1675    }
1676
1677    private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1678            ActivityOptions aOptions, boolean launchToSideAllowed) {
1679        final int launchStackId =
1680                (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1681
1682        if (isValidLaunchStackId(launchStackId, r)) {
1683            return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
1684        }
1685
1686        if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_TO_SIDE) == 0) {
1687            return null;
1688        }
1689
1690        // The parent activity doesn't want to launch the activity on top of itself, but
1691        // instead tries to put it onto other side in side-by-side mode.
1692        final ActivityStack parentStack = task != null ? task.stack
1693                : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1694                : mSupervisor.mFocusedStack;
1695        if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1696            // If parent was in docked stack, the natural place to launch another activity
1697            // will be fullscreen, so it can appear alongside the docked window.
1698            return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1699        } else {
1700            // If the parent is not in the docked stack, we check if there is docked window
1701            // and if yes, we will launch into that stack. If not, we just put the new
1702            // activity into parent's stack, because we can't find a better place.
1703            final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
1704            if (stack != null && !stack.isStackVisibleLocked()) {
1705                // There is a docked stack, but it isn't visible, so we can't launch into that.
1706                return null;
1707            } else {
1708                return stack;
1709            }
1710        }
1711    }
1712
1713    private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1714        if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1715                || !StackId.isStaticStack(stackId)) {
1716            return false;
1717        }
1718
1719        final boolean resizeable = r.isResizeable() || mService.mForceResizableActivities;
1720
1721        if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !resizeable) {
1722            return false;
1723        }
1724
1725        if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1726            return false;
1727        }
1728
1729        final boolean supportsPip = mService.mSupportsPictureInPicture
1730                && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1731        if (stackId == PINNED_STACK_ID && !supportsPip) {
1732            return false;
1733        }
1734        return true;
1735    }
1736
1737    Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1738        Rect newBounds = null;
1739        if (options != null && (r.isResizeable() || (inTask != null && inTask.mResizeable))) {
1740            if (mSupervisor.canUseActivityOptionsLaunchBounds(
1741                    options, options.getLaunchStackId())) {
1742                newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
1743            }
1744        }
1745        return newBounds;
1746    }
1747
1748    void setWindowManager(WindowManagerService wm) {
1749        mWindowManager = wm;
1750    }
1751
1752    void removePendingActivityLaunchesLocked(ActivityStack stack) {
1753        for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
1754            PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
1755            if (pal.stack == stack) {
1756                mPendingActivityLaunches.remove(palNdx);
1757            }
1758        }
1759    }
1760}
1761