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