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