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