ActivityStarter.java revision 275561a74677f9d6c8f3f2cebc3cfea416ca586d
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        mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
597        boolean componentSpecified = intent.getComponent() != null;
598
599        // Save a copy in case ephemeral needs it
600        final Intent ephemeralIntent = new Intent(intent);
601        // Don't modify the client's object!
602        intent = new Intent(intent);
603
604        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
605        if (rInfo == null) {
606            UserInfo userInfo = mSupervisor.getUserInfo(userId);
607            if (userInfo != null && userInfo.isManagedProfile()) {
608                // Special case for managed profiles, if attempting to launch non-cryto aware
609                // app in a locked managed profile from an unlocked parent allow it to resolve
610                // as user will be sent via confirm credentials to unlock the profile.
611                UserManager userManager = UserManager.get(mService.mContext);
612                UserInfo parent = null;
613                long token = Binder.clearCallingIdentity();
614                try {
615                    parent = userManager.getProfileParent(userId);
616                } finally {
617                    Binder.restoreCallingIdentity(token);
618                }
619                if (parent != null
620                        && userManager.isUserUnlocked(parent.getUserHandle())
621                        && !userManager.isUserUnlocked(userInfo.getUserHandle())) {
622                    rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
623                            PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
624                }
625            }
626        }
627        // Collect information about the target of the Intent.
628        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
629
630        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
631        ActivityStackSupervisor.ActivityContainer container =
632                (ActivityStackSupervisor.ActivityContainer)iContainer;
633        synchronized (mService) {
634            if (container != null && container.mParentActivity != null &&
635                    container.mParentActivity.state != RESUMED) {
636                // Cannot start a child activity if the parent is not resumed.
637                return ActivityManager.START_CANCELED;
638            }
639            final int realCallingPid = Binder.getCallingPid();
640            final int realCallingUid = Binder.getCallingUid();
641            int callingPid;
642            if (callingUid >= 0) {
643                callingPid = -1;
644            } else if (caller == null) {
645                callingPid = realCallingPid;
646                callingUid = realCallingUid;
647            } else {
648                callingPid = callingUid = -1;
649            }
650
651            final ActivityStack stack;
652            if (container == null || container.mStack.isOnHomeDisplay()) {
653                stack = mSupervisor.mFocusedStack;
654            } else {
655                stack = container.mStack;
656            }
657            stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
658            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
659                    "Starting activity when config will change = " + stack.mConfigWillChange);
660
661            final long origId = Binder.clearCallingIdentity();
662
663            if (aInfo != null &&
664                    (aInfo.applicationInfo.privateFlags
665                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
666                // This may be a heavy-weight process!  Check to see if we already
667                // have another, different heavy-weight process running.
668                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
669                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
670                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
671                            || !heavy.processName.equals(aInfo.processName))) {
672                        int appCallingUid = callingUid;
673                        if (caller != null) {
674                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
675                            if (callerApp != null) {
676                                appCallingUid = callerApp.info.uid;
677                            } else {
678                                Slog.w(TAG, "Unable to find app for caller " + caller
679                                        + " (pid=" + callingPid + ") when starting: "
680                                        + intent.toString());
681                                ActivityOptions.abort(options);
682                                return ActivityManager.START_PERMISSION_DENIED;
683                            }
684                        }
685
686                        IIntentSender target = mService.getIntentSenderLocked(
687                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
688                                appCallingUid, userId, null, null, 0, new Intent[] { intent },
689                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
690                                        | PendingIntent.FLAG_ONE_SHOT, null);
691
692                        Intent newIntent = new Intent();
693                        if (requestCode >= 0) {
694                            // Caller is requesting a result.
695                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
696                        }
697                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
698                                new IntentSender(target));
699                        if (heavy.activities.size() > 0) {
700                            ActivityRecord hist = heavy.activities.get(0);
701                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
702                                    hist.packageName);
703                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
704                                    hist.task.taskId);
705                        }
706                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
707                                aInfo.packageName);
708                        newIntent.setFlags(intent.getFlags());
709                        newIntent.setClassName("android",
710                                HeavyWeightSwitcherActivity.class.getName());
711                        intent = newIntent;
712                        resolvedType = null;
713                        caller = null;
714                        callingUid = Binder.getCallingUid();
715                        callingPid = Binder.getCallingPid();
716                        componentSpecified = true;
717                        rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
718                        aInfo = rInfo != null ? rInfo.activityInfo : null;
719                        if (aInfo != null) {
720                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
721                        }
722                    }
723                }
724            }
725
726            final ActivityRecord[] outRecord = new ActivityRecord[1];
727            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
728                    aInfo, rInfo, voiceSession, voiceInteractor,
729                    resultTo, resultWho, requestCode, callingPid,
730                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
731                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
732                    inTask);
733
734            Binder.restoreCallingIdentity(origId);
735
736            if (stack.mConfigWillChange) {
737                // If the caller also wants to switch to a new configuration,
738                // do so now.  This allows a clean switch, as we are waiting
739                // for the current activity to pause (so we will not destroy
740                // it), and have not yet started the next activity.
741                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
742                        "updateConfiguration()");
743                stack.mConfigWillChange = false;
744                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
745                        "Updating to new configuration after starting activity.");
746                mService.updateConfigurationLocked(config, null, false);
747            }
748
749            if (outResult != null) {
750                outResult.result = res;
751                if (res == ActivityManager.START_SUCCESS) {
752                    mSupervisor.mWaitingActivityLaunched.add(outResult);
753                    do {
754                        try {
755                            mService.wait();
756                        } catch (InterruptedException e) {
757                        }
758                    } while (!outResult.timeout && outResult.who == null);
759                } else if (res == START_TASK_TO_FRONT) {
760                    ActivityRecord r = stack.topRunningActivityLocked();
761                    if (r.nowVisible && r.state == RESUMED) {
762                        outResult.timeout = false;
763                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
764                        outResult.totalTime = 0;
765                        outResult.thisTime = 0;
766                    } else {
767                        outResult.thisTime = SystemClock.uptimeMillis();
768                        mSupervisor.mWaitingActivityVisible.add(outResult);
769                        do {
770                            try {
771                                mService.wait();
772                            } catch (InterruptedException e) {
773                            }
774                        } while (!outResult.timeout && outResult.who == null);
775                    }
776                }
777            }
778
779            final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
780                    : null;
781            final boolean processRunning = outRecord[0] != null &&
782                    mService.mProcessNames.get(outRecord[0].processName,
783                            outRecord[0].appInfo.uid) != null;
784            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
785                    processRunning);
786            return res;
787        }
788    }
789
790    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
791            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
792            Bundle bOptions, int userId) {
793        if (intents == null) {
794            throw new NullPointerException("intents is null");
795        }
796        if (resolvedTypes == null) {
797            throw new NullPointerException("resolvedTypes is null");
798        }
799        if (intents.length != resolvedTypes.length) {
800            throw new IllegalArgumentException("intents are length different than resolvedTypes");
801        }
802
803
804        int callingPid;
805        if (callingUid >= 0) {
806            callingPid = -1;
807        } else if (caller == null) {
808            callingPid = Binder.getCallingPid();
809            callingUid = Binder.getCallingUid();
810        } else {
811            callingPid = callingUid = -1;
812        }
813        final long origId = Binder.clearCallingIdentity();
814        try {
815            synchronized (mService) {
816                ActivityRecord[] outActivity = new ActivityRecord[1];
817                for (int i=0; i<intents.length; i++) {
818                    Intent intent = intents[i];
819                    if (intent == null) {
820                        continue;
821                    }
822
823                    // Refuse possible leaked file descriptors
824                    if (intent != null && intent.hasFileDescriptors()) {
825                        throw new IllegalArgumentException("File descriptors passed in Intent");
826                    }
827
828                    boolean componentSpecified = intent.getComponent() != null;
829
830                    // Don't modify the client's object!
831                    intent = new Intent(intent);
832
833                    // Collect information about the target of the Intent.
834                    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
835                            null, userId);
836                    // TODO: New, check if this is correct
837                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
838
839                    if (aInfo != null &&
840                            (aInfo.applicationInfo.privateFlags
841                                    & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
842                        throw new IllegalArgumentException(
843                                "FLAG_CANT_SAVE_STATE not supported here");
844                    }
845
846                    ActivityOptions options = ActivityOptions.fromBundle(
847                            i == intents.length - 1 ? bOptions : null);
848                    int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
849                            resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
850                            callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
851                            options, false, componentSpecified, outActivity, null, null);
852                    if (res < 0) {
853                        return res;
854                    }
855
856                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
857                }
858            }
859        } finally {
860            Binder.restoreCallingIdentity(origId);
861        }
862
863        return START_SUCCESS;
864    }
865
866    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
867            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
868            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
869
870        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
871                voiceInteractor);
872
873        computeLaunchingTaskFlags();
874
875        computeSourceStack();
876
877        mIntent.setFlags(mLaunchFlags);
878
879        ActivityRecord intentActivity = getReusableIntentActivity();
880
881        if (intentActivity != null) {
882            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
883            // still needs to be a lock task mode violation since the task gets cleared out and
884            // the device would otherwise leave the locked task.
885            if (mSupervisor.isLockTaskModeViolation(intentActivity.task,
886                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
887                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
888                mSupervisor.showLockTaskToast();
889                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
890                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
891            }
892
893            if (mStartActivity.task == null) {
894                mStartActivity.task = intentActivity.task;
895            }
896            if (intentActivity.task.intent == null) {
897                // This task was started because of movement of the activity based on affinity...
898                // Now that we are actually launching it, we can assign the base intent.
899                intentActivity.task.setIntent(mStartActivity);
900            }
901
902            // This code path leads to delivering a new intent, we want to make sure we schedule it
903            // as the first operation, in case the activity will be resumed as a result of later
904            // operations.
905            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
906                    || mLaunchSingleInstance || mLaunchSingleTask) {
907                // In this situation we want to remove all activities from the task up to the one
908                // being started. In most cases this means we are resetting the task to its initial
909                // state.
910                final ActivityRecord top = intentActivity.task.performClearTaskForReuseLocked(
911                        mStartActivity, mLaunchFlags);
912                if (top != null) {
913                    if (top.frontOfTask) {
914                        // Activity aliases may mean we use different intents for the top activity,
915                        // so make sure the task now has the identity of the new intent.
916                        top.task.setIntent(mStartActivity);
917                    }
918                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
919                    top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
920                            mStartActivity.launchedFromPackage);
921                }
922            }
923
924            intentActivity = setTargetStackAndMoveToFrontIfNeeded(intentActivity);
925
926            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
927                // We don't need to start a new activity, and the client said not to do anything
928                // if that is the case, so this is it!  And for paranoia, make sure we have
929                // correctly resumed the top activity.
930                resumeTargetStackIfNeeded();
931                return START_RETURN_INTENT_TO_CALLER;
932            }
933
934            setTaskFromIntentActivity(intentActivity);
935
936            if (!mAddingToTask && mReuseTask == null) {
937                // We didn't do anything...  but it was needed (a.k.a., client don't use that
938                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
939                resumeTargetStackIfNeeded();
940                return START_TASK_TO_FRONT;
941            }
942        }
943
944        if (mStartActivity.packageName == null) {
945            if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
946                mStartActivity.resultTo.task.stack.sendActivityResultLocked(
947                        -1, mStartActivity.resultTo, mStartActivity.resultWho,
948                        mStartActivity.requestCode, RESULT_CANCELED, null);
949            }
950            ActivityOptions.abort(mOptions);
951            return START_CLASS_NOT_FOUND;
952        }
953
954        // If the activity being launched is the same as the one currently at the top, then
955        // we need to check if it should only be launched once.
956        final ActivityStack topStack = mSupervisor.mFocusedStack;
957        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
958        final boolean dontStart = top != null && mStartActivity.resultTo == null
959                && top.realActivity.equals(mStartActivity.realActivity)
960                && top.userId == mStartActivity.userId
961                && top.app != null && top.app.thread != null
962                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
963                || mLaunchSingleTop || mLaunchSingleTask);
964        if (dontStart) {
965            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
966            // For paranoia, make sure we have correctly resumed the top activity.
967            topStack.mLastPausedActivity = null;
968            if (mDoResume) {
969                mSupervisor.resumeFocusedStackTopActivityLocked();
970            }
971            ActivityOptions.abort(mOptions);
972            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
973                // We don't need to start a new activity, and the client said not to do
974                // anything if that is the case, so this is it!
975                return START_RETURN_INTENT_TO_CALLER;
976            }
977            top.deliverNewIntentLocked(
978                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
979            return START_DELIVERED_TO_TOP;
980        }
981
982        boolean newTask = false;
983        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
984                ? mSourceRecord.task : null;
985
986        // Should this be considered a new task?
987        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
988                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
989            newTask = true;
990            setTaskFromReuseOrCreateNewTask(taskToAffiliate);
991
992            if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
993                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
994                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
995            }
996            if (!mMovedHome) {
997                updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
998            }
999        } else if (mSourceRecord != null) {
1000            if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1001                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1002                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1003            }
1004
1005            final int result = setTaskFromSourceRecord();
1006            if (result != START_SUCCESS) {
1007                return result;
1008            }
1009        } else if (mInTask != null) {
1010            // The caller is asking that the new activity be started in an explicit
1011            // task it has provided to us.
1012            if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1013                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1014                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1015            }
1016
1017            final int result = setTaskFromInTask();
1018            if (result != START_SUCCESS) {
1019                return result;
1020            }
1021        } else {
1022            // This not being started from an existing activity, and not part of a new task...
1023            // just put it in the top task, though these days this case should never happen.
1024            setTaskToCurrentTopOrCreateNewTask();
1025        }
1026
1027        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1028                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1029
1030        if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1031            mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1032        }
1033        if (newTask) {
1034            EventLog.writeEvent(
1035                    EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1036        }
1037        ActivityStack.logStartActivity(
1038                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1039        mTargetStack.mLastPausedActivity = null;
1040        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1041        if (mDoResume) {
1042            if (!mLaunchTaskBehind) {
1043                // TODO(b/26381750): Remove this code after verification that all the decision
1044                // points above moved targetStack to the front which will also set the focus
1045                // activity.
1046                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1047            }
1048            if (mTargetStack.isFocusable()) {
1049                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1050                        mOptions);
1051            } else {
1052                // If the activity is not focusable, we can't resume it, but still would like to
1053                // make sure it becomes visible as it starts (this will also trigger entry
1054                // animation). An example of this are PIP activities.
1055                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1056                // Go ahead and tell window manager to execute app transition for this activity
1057                // since the app transition will not be triggered through the resume channel.
1058                mWindowManager.executeAppTransition();
1059            }
1060        } else {
1061            mTargetStack.addRecentActivityLocked(mStartActivity);
1062        }
1063        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1064
1065        final int preferredLaunchStackId =
1066                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1067        mSupervisor.showNonResizeableDockToastIfNeeded(
1068                mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
1069
1070        return START_SUCCESS;
1071    }
1072
1073    private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1074            boolean doResume, int startFlags, ActivityRecord sourceRecord,
1075            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1076        reset();
1077
1078        mStartActivity = r;
1079        mIntent = r.intent;
1080        mOptions = options;
1081        mCallingUid = r.launchedFromUid;
1082        mSourceRecord = sourceRecord;
1083        mVoiceSession = voiceSession;
1084        mVoiceInteractor = voiceInteractor;
1085
1086        mLaunchBounds = getOverrideBounds(r, options, inTask);
1087
1088        mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1089        mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1090        mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1091        mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1092                r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1093        mLaunchTaskBehind = r.mLaunchTaskBehind
1094                && !mLaunchSingleTask && !mLaunchSingleInstance
1095                && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1096
1097        sendNewTaskResultRequestIfNeeded();
1098
1099        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1100            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1101        }
1102
1103        // If we are actually going to launch in to a new task, there are some cases where
1104        // we further want to do multiple task.
1105        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1106            if (mLaunchTaskBehind
1107                    || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1108                mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1109            }
1110        }
1111
1112        // We'll invoke onUserLeaving before onPause only if the launching
1113        // activity did not explicitly state that this is an automated launch.
1114        mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1115        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1116                "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1117
1118        // If the caller has asked not to resume at this point, we make note
1119        // of this in the record so that we can skip it when trying to find
1120        // the top running activity.
1121        mDoResume = doResume;
1122        if (!doResume || !mSupervisor.okToShowLocked(r)) {
1123            r.delayedResume = true;
1124            mDoResume = false;
1125        }
1126
1127        mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1128
1129        mInTask = inTask;
1130        // In some flows in to this function, we retrieve the task record and hold on to it
1131        // without a lock before calling back in to here...  so the task at this point may
1132        // not actually be in recents.  Check for that, and if it isn't in recents just
1133        // consider it invalid.
1134        if (inTask != null && !inTask.inRecents) {
1135            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1136            mInTask = null;
1137        }
1138
1139        mStartFlags = startFlags;
1140        // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1141        // is the same as the one making the call...  or, as a special case, if we do not know
1142        // the caller then we count the current top activity as the caller.
1143        if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1144            ActivityRecord checkedCaller = sourceRecord;
1145            if (checkedCaller == null) {
1146                checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1147                        mNotTop);
1148            }
1149            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1150                // Caller is not the same as launcher, so always needed.
1151                mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1152            }
1153        }
1154
1155        mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1156    }
1157
1158    private void sendNewTaskResultRequestIfNeeded() {
1159        if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1160                && mStartActivity.resultTo.task.stack != null) {
1161            // For whatever reason this activity is being launched into a new task...
1162            // yet the caller has requested a result back.  Well, that is pretty messed up,
1163            // so instead immediately send back a cancel and let the new task continue launched
1164            // as normal without a dependency on its originator.
1165            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1166            mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1167                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1168            mStartActivity.resultTo = null;
1169        }
1170    }
1171
1172    private void computeLaunchingTaskFlags() {
1173        // If the caller is not coming from another activity, but has given us an explicit task into
1174        // which they would like us to launch the new activity, then let's see about doing that.
1175        if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1176            final Intent baseIntent = mInTask.getBaseIntent();
1177            final ActivityRecord root = mInTask.getRootActivity();
1178            if (baseIntent == null) {
1179                ActivityOptions.abort(mOptions);
1180                throw new IllegalArgumentException("Launching into task without base intent: "
1181                        + mInTask);
1182            }
1183
1184            // If this task is empty, then we are adding the first activity -- it
1185            // determines the root, and must be launching as a NEW_TASK.
1186            if (mLaunchSingleInstance || mLaunchSingleTask) {
1187                if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1188                    ActivityOptions.abort(mOptions);
1189                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1190                            + mStartActivity + " into different task " + mInTask);
1191                }
1192                if (root != null) {
1193                    ActivityOptions.abort(mOptions);
1194                    throw new IllegalArgumentException("Caller with mInTask " + mInTask
1195                            + " has root " + root + " but target is singleInstance/Task");
1196                }
1197            }
1198
1199            // If task is empty, then adopt the interesting intent launch flags in to the
1200            // activity being started.
1201            if (root == null) {
1202                final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1203                        | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1204                mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1205                        | (baseIntent.getFlags() & flagsOfInterest);
1206                mIntent.setFlags(mLaunchFlags);
1207                mInTask.setIntent(mStartActivity);
1208                mAddingToTask = true;
1209
1210                // If the task is not empty and the caller is asking to start it as the root of
1211                // a new task, then we don't actually want to start this on the task. We will
1212                // bring the task to the front, and possibly give it a new intent.
1213            } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1214                mAddingToTask = false;
1215
1216            } else {
1217                mAddingToTask = true;
1218            }
1219
1220            mReuseTask = mInTask;
1221        } else {
1222            mInTask = null;
1223            // Launch ResolverActivity in the source task, so that it stays in the task bounds
1224            // when in freeform workspace.
1225            // Also put noDisplay activities in the source task. These by itself can be placed
1226            // in any task/stack, however it could launch other activities like ResolverActivity,
1227            // and we want those to stay in the original task.
1228            if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1229                    && mSourceRecord.isFreeform())  {
1230                mAddingToTask = true;
1231            }
1232        }
1233
1234        if (mInTask == null) {
1235            if (mSourceRecord == null) {
1236                // This activity is not being started from another...  in this
1237                // case we -always- start a new task.
1238                if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1239                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1240                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1241                    mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1242                }
1243            } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1244                // The original activity who is starting us is running as a single
1245                // instance...  this new activity it is starting must go on its
1246                // own task.
1247                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1248            } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1249                // The activity being started is a single instance...  it always
1250                // gets launched into its own task.
1251                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1252            }
1253        }
1254    }
1255
1256    private void computeSourceStack() {
1257        if (mSourceRecord == null) {
1258            mSourceStack = null;
1259            return;
1260        }
1261        if (!mSourceRecord.finishing) {
1262            mSourceStack = mSourceRecord.task.stack;
1263            return;
1264        }
1265
1266        // If the source is finishing, we can't further count it as our source. This is because the
1267        // task it is associated with may now be empty and on its way out, so we don't want to
1268        // blindly throw it in to that task.  Instead we will take the NEW_TASK flow and try to find
1269        // a task for it. But save the task information so it can be used when creating the new task.
1270        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1271            Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1272                    + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1273            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1274            mNewTaskInfo = mSourceRecord.info;
1275            mNewTaskIntent = mSourceRecord.task.intent;
1276        }
1277        mSourceRecord = null;
1278        mSourceStack = null;
1279    }
1280
1281    /**
1282     * Decide whether the new activity should be inserted into an existing task. Returns null
1283     * if not or an ActivityRecord with the task into which the new activity should be added.
1284     */
1285    private ActivityRecord getReusableIntentActivity() {
1286        // We may want to try to place the new activity in to an existing task.  We always
1287        // do this if the target activity is singleTask or singleInstance; we will also do
1288        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1289        // us to still place it in a new task: multi task, always doc mode, or being asked to
1290        // launch this as a new task behind the current one.
1291        boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1292                (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1293                || mLaunchSingleInstance || mLaunchSingleTask;
1294        // If bring to front is requested, and no result is requested and we have not been given
1295        // an explicit task to launch in to, and we can find a task that was started with this
1296        // same component, then instead of launching bring that one to the front.
1297        putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1298        ActivityRecord intentActivity = null;
1299        if (putIntoExistingTask) {
1300            // See if there is a task to bring to the front.  If this is a SINGLE_INSTANCE
1301            // activity, there can be one and only one instance of it in the history, and it is
1302            // always in its own unique task, so we do a special search.
1303            intentActivity = mLaunchSingleInstance ? mSupervisor.findActivityLocked(mIntent, mStartActivity.info)
1304                    : mSupervisor.findTaskLocked(mStartActivity);
1305        }
1306        return intentActivity;
1307    }
1308
1309    private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1310        mTargetStack = intentActivity.task.stack;
1311        mTargetStack.mLastPausedActivity = null;
1312        // If the target task is not in the front, then we need to bring it to the front...
1313        // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1314        // the same behavior as if a new instance was being started, which means not bringing it
1315        // to the front if the caller is not itself in the front.
1316        final ActivityStack focusStack = mSupervisor.getFocusedStack();
1317        ActivityRecord curTop = (focusStack == null)
1318                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1319
1320        if (curTop != null && (curTop.task != intentActivity.task ||
1321                curTop.task != focusStack.topTask())) {
1322            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1323            if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1324                    mSourceStack.topActivity().task == mSourceRecord.task)) {
1325                // We really do want to push this one into the user's face, right now.
1326                if (mLaunchTaskBehind && mSourceRecord != null) {
1327                    intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1328                }
1329                mMovedHome = true;
1330                final ActivityStack launchStack =
1331                        getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1332                                mOptions, true);
1333                if (launchStack == null || launchStack == mTargetStack) {
1334                    // We only want to move to the front, if we aren't going to launch on a
1335                    // different stack. If we launch on a different stack, we will put the
1336                    // task on top there.
1337                    mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1338                            mOptions, mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1339                    mMovedToFront = true;
1340                }
1341                updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
1342                mOptions = null;
1343            }
1344        }
1345        if (!mMovedToFront && mDoResume) {
1346            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1347                    + " from " + intentActivity);
1348            mTargetStack.moveToFront("intentActivityFound");
1349        }
1350
1351        // If the caller has requested that the target task be reset, then do so.
1352        if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1353            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1354        }
1355        return intentActivity;
1356    }
1357
1358    private void updateTaskReturnToType(
1359            TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1360        if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1361                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1362            // Caller wants to appear on home activity.
1363            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1364            return;
1365        } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1366            // Task will be launched over the home stack, so return home.
1367            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1368            return;
1369        }
1370
1371        // Else we are coming from an application stack so return to an application.
1372        task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1373    }
1374
1375    private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1376        if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1377                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1378            // The caller has requested to completely replace any existing task with its new
1379            // activity. Well that should not be too hard...
1380            mReuseTask = intentActivity.task;
1381            mReuseTask.performClearTaskLocked();
1382            mReuseTask.setIntent(mStartActivity);
1383        } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1384                || mLaunchSingleInstance || mLaunchSingleTask) {
1385            ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1386                    mLaunchFlags);
1387            if (top == null) {
1388                // A special case: we need to start the activity because it is not currently
1389                // running, and the caller has asked to clear the current task to have this
1390                // activity at the top.
1391                mAddingToTask = true;
1392                // Now pretend like this activity is being started by the top of its task, so it
1393                // is put in the right place.
1394                mSourceRecord = intentActivity;
1395                final TaskRecord task = mSourceRecord.task;
1396                if (task != null && task.stack == null) {
1397                    // Target stack got cleared when we all activities were removed above.
1398                    // Go ahead and reset it.
1399                    mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1400                            null /* bounds */, mLaunchFlags, mOptions);
1401                    mTargetStack.addTask(task,
1402                            !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1403                }
1404            }
1405        } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1406            // In this case the top activity on the task is the same as the one being launched,
1407            // so we take that as a request to bring the task to the foreground. If the top
1408            // activity in the task is the root activity, deliver this new intent to it if it
1409            // desires.
1410            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1411                    && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1412                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1413                        intentActivity.task);
1414                if (intentActivity.frontOfTask) {
1415                    intentActivity.task.setIntent(mStartActivity);
1416                }
1417                intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1418                        mStartActivity.launchedFromPackage);
1419            } else if (!mStartActivity.intent.filterEquals(intentActivity.intent)) {
1420                // In this case we are launching the root activity of the task, but with a
1421                // different intent. We should start a new instance on top.
1422                mAddingToTask = true;
1423                mSourceRecord = intentActivity;
1424            }
1425        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1426            // In this case an activity is being launched in to an existing task, without
1427            // resetting that task. This is typically the situation of launching an activity
1428            // from a notification or shortcut. We want to place the new activity on top of the
1429            // current task.
1430            mAddingToTask = true;
1431            mSourceRecord = intentActivity;
1432        } else if (!intentActivity.task.rootWasReset) {
1433            // In this case we are launching into an existing task that has not yet been started
1434            // from its front door. The current task has been brought to the front. Ideally,
1435            // we'd probably like to place this new task at the bottom of its stack, but that's
1436            // a little hard to do with the current organization of the code so for now we'll
1437            // just drop it.
1438            intentActivity.task.setIntent(mStartActivity);
1439        }
1440    }
1441
1442    private void resumeTargetStackIfNeeded() {
1443        if (mDoResume) {
1444            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1445            if (!mMovedToFront) {
1446                // Make sure to notify Keyguard as well if we are not running an app transition
1447                // later.
1448                mSupervisor.notifyActivityDrawnForKeyguard();
1449            }
1450        } else {
1451            ActivityOptions.abort(mOptions);
1452        }
1453        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1454    }
1455
1456    private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1457        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1458                mOptions);
1459        if (mDoResume) {
1460            mTargetStack.moveToFront("startingNewTask");
1461        }
1462
1463        if (mReuseTask == null) {
1464            final TaskRecord task = mTargetStack.createTaskRecord(
1465                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1466                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1467                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1468                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1469            mStartActivity.setTask(task, taskToAffiliate);
1470            if (mLaunchBounds != null) {
1471                final int stackId = mTargetStack.mStackId;
1472                if (StackId.resizeStackWithLaunchBounds(stackId)) {
1473                    mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE);
1474                } else {
1475                    mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1476                }
1477            }
1478            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1479                    "Starting new activity " +
1480                            mStartActivity + " in new task " + mStartActivity.task);
1481        } else {
1482            mStartActivity.setTask(mReuseTask, taskToAffiliate);
1483        }
1484    }
1485
1486    private int setTaskFromSourceRecord() {
1487        final TaskRecord sourceTask = mSourceRecord.task;
1488        // We only want to allow changing stack if the target task is not the top one,
1489        // otherwise we would move the launching task to the other side, rather than show
1490        // two side by side.
1491        final boolean launchToSideAllowed = sourceTask.stack.topTask() != sourceTask;
1492        mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, launchToSideAllowed);
1493
1494        if (mTargetStack == null) {
1495            mTargetStack = sourceTask.stack;
1496        } else if (mTargetStack != sourceTask.stack) {
1497            mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1498                    ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1499        }
1500        if (mDoResume) {
1501            mTargetStack.moveToFront("sourceStackToFront");
1502        }
1503        final TaskRecord topTask = mTargetStack.topTask();
1504        if (topTask != sourceTask) {
1505            mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1506                    mStartActivity.appTimeTracker, "sourceTaskToFront");
1507        }
1508        if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1509            // In this case, we are adding the activity to an existing task, but the caller has
1510            // asked to clear that task if the activity is already running.
1511            ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1512            mKeepCurTransition = true;
1513            if (top != null) {
1514                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1515                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1516                // For paranoia, make sure we have correctly resumed the top activity.
1517                mTargetStack.mLastPausedActivity = null;
1518                if (mDoResume) {
1519                    mSupervisor.resumeFocusedStackTopActivityLocked();
1520                }
1521                ActivityOptions.abort(mOptions);
1522                return START_DELIVERED_TO_TOP;
1523            }
1524        } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1525            // In this case, we are launching an activity in our own task that may already be
1526            // running somewhere in the history, and we want to shuffle it to the front of the
1527            // stack if so.
1528            final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1529            if (top != null) {
1530                final TaskRecord task = top.task;
1531                task.moveActivityToFrontLocked(top);
1532                top.updateOptionsLocked(mOptions);
1533                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1534                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1535                mTargetStack.mLastPausedActivity = null;
1536                if (mDoResume) {
1537                    mSupervisor.resumeFocusedStackTopActivityLocked();
1538                }
1539                return START_DELIVERED_TO_TOP;
1540            }
1541        }
1542
1543        // An existing activity is starting this new activity, so we want to keep the new one in
1544        // the same task as the one that is starting it.
1545        mStartActivity.setTask(sourceTask, null);
1546        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1547                + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1548        return START_SUCCESS;
1549    }
1550
1551    private int setTaskFromInTask() {
1552        if (mLaunchBounds != null) {
1553            mInTask.updateOverrideConfiguration(mLaunchBounds);
1554            int stackId = mInTask.getLaunchStackId();
1555            if (stackId != mInTask.stack.mStackId) {
1556                final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
1557                        mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1558                stackId = stack.mStackId;
1559            }
1560            if (StackId.resizeStackWithLaunchBounds(stackId)) {
1561                mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE);
1562            }
1563        }
1564        mTargetStack = mInTask.stack;
1565        mTargetStack.moveTaskToFrontLocked(
1566                mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1567
1568        // Check whether we should actually launch the new activity in to the task,
1569        // or just reuse the current activity on top.
1570        ActivityRecord top = mInTask.getTopActivity();
1571        if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1572            if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1573                    || mLaunchSingleTop || mLaunchSingleTask) {
1574                ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1575                if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1576                    // We don't need to start a new activity, and the client said not to do
1577                    // anything if that is the case, so this is it!
1578                    return START_RETURN_INTENT_TO_CALLER;
1579                }
1580                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1581                return START_DELIVERED_TO_TOP;
1582            }
1583        }
1584
1585        if (!mAddingToTask) {
1586            // We don't actually want to have this activity added to the task, so just
1587            // stop here but still tell the caller that we consumed the intent.
1588            ActivityOptions.abort(mOptions);
1589            return START_TASK_TO_FRONT;
1590        }
1591
1592        mStartActivity.setTask(mInTask, null);
1593        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1594                "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1595
1596        return START_SUCCESS;
1597    }
1598
1599    private void setTaskToCurrentTopOrCreateNewTask() {
1600        mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1601                mOptions);
1602        if (mDoResume) {
1603            mTargetStack.moveToFront("addingToTopTask");
1604        }
1605        final ActivityRecord prev = mTargetStack.topActivity();
1606        final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1607                        mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1608                        mStartActivity.info, mIntent, null, null, true);
1609        mStartActivity.setTask(task, null);
1610        mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1611        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1612                "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1613    }
1614
1615    private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1616            boolean launchSingleTask, int launchFlags) {
1617        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1618                (launchSingleInstance || launchSingleTask)) {
1619            // We have a conflict between the Intent and the Activity manifest, manifest wins.
1620            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1621                    "\"singleInstance\" or \"singleTask\"");
1622            launchFlags &=
1623                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1624        } else {
1625            switch (r.info.documentLaunchMode) {
1626                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1627                    break;
1628                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1629                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1630                    break;
1631                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1632                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1633                    break;
1634                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1635                    launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1636                    break;
1637            }
1638        }
1639        return launchFlags;
1640    }
1641
1642    final void doPendingActivityLaunchesLocked(boolean doResume) {
1643        while (!mPendingActivityLaunches.isEmpty()) {
1644            final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1645            final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
1646            try {
1647                final int result = startActivityUnchecked(
1648                        pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1649                postStartActivityUncheckedProcessing(
1650                        pal.r, result, mSupervisor.mFocusedStack.mStackId);
1651            } catch (Exception e) {
1652                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1653                pal.sendErrorResult(e.getMessage());
1654            }
1655        }
1656    }
1657
1658    private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1659            int launchFlags, ActivityOptions aOptions) {
1660        final TaskRecord task = r.task;
1661        if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1662            return mSupervisor.mHomeStack;
1663        }
1664
1665        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions, true);
1666        if (stack != null) {
1667            return stack;
1668        }
1669
1670        if (task != null && task.stack != null) {
1671            stack = task.stack;
1672            if (stack.isOnHomeDisplay()) {
1673                if (mSupervisor.mFocusedStack != stack) {
1674                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1675                            "computeStackFocus: Setting " + "focused stack to r=" + r
1676                                    + " task=" + task);
1677                } else {
1678                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1679                            "computeStackFocus: Focused stack already="
1680                                    + mSupervisor.mFocusedStack);
1681                }
1682            }
1683            return stack;
1684        }
1685
1686        final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1687        if (container != null) {
1688            // The first time put it on the desired stack, after this put on task stack.
1689            r.mInitialActivityContainer = null;
1690            return container.mStack;
1691        }
1692
1693        // The fullscreen stack can contain any task regardless of if the task is resizeable
1694        // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1695        // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1696        // we can also put it in the focused stack.
1697        final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1698        final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1699                || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1700                || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
1701        if (canUseFocusedStack && (!newTask
1702                || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1703            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1704                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1705            return mSupervisor.mFocusedStack;
1706        }
1707
1708        // We first try to put the task in the first dynamic stack.
1709        final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1710        for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1711            stack = homeDisplayStacks.get(stackNdx);
1712            if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1713                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1714                        "computeStackFocus: Setting focused stack=" + stack);
1715                return stack;
1716            }
1717        }
1718
1719        // If there is no suitable dynamic stack then we figure out which static stack to use.
1720        final int stackId = task != null ? task.getLaunchStackId() :
1721                bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1722                        FULLSCREEN_WORKSPACE_STACK_ID;
1723        stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1724        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1725                + r + " stackId=" + stack.mStackId);
1726        return stack;
1727    }
1728
1729    private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1730            ActivityOptions aOptions, boolean launchToSideAllowed) {
1731        final int launchStackId =
1732                (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1733
1734        if (isValidLaunchStackId(launchStackId, r)) {
1735            return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
1736        } else if (launchStackId == DOCKED_STACK_ID) {
1737            // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1738            // for this activity, so we put the activity in the fullscreen stack.
1739            return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1740        }
1741
1742        if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
1743            return null;
1744        }
1745
1746        // The parent activity doesn't want to launch the activity on top of itself, but
1747        // instead tries to put it onto other side in side-by-side mode.
1748        final ActivityStack parentStack = task != null ? task.stack
1749                : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1750                : mSupervisor.mFocusedStack;
1751        if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1752            // If parent was in docked stack, the natural place to launch another activity
1753            // will be fullscreen, so it can appear alongside the docked window.
1754            return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1755        } else {
1756            // If the parent is not in the docked stack, we check if there is docked window
1757            // and if yes, we will launch into that stack. If not, we just put the new
1758            // activity into parent's stack, because we can't find a better place.
1759            final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
1760            if (stack != null && stack.getStackVisibilityLocked() == STACK_INVISIBLE) {
1761                // There is a docked stack, but it isn't visible, so we can't launch into that.
1762                return null;
1763            } else {
1764                return stack;
1765            }
1766        }
1767    }
1768
1769    private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1770        if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1771                || !StackId.isStaticStack(stackId)) {
1772            return false;
1773        }
1774
1775        if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
1776            return true;
1777        }
1778
1779        if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !r.isResizeableOrForced()) {
1780            return false;
1781        }
1782
1783        if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1784            return false;
1785        }
1786
1787        final boolean supportsPip = mService.mSupportsPictureInPicture
1788                && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1789        if (stackId == PINNED_STACK_ID && !supportsPip) {
1790            return false;
1791        }
1792        return true;
1793    }
1794
1795    Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1796        Rect newBounds = null;
1797        if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
1798            if (mSupervisor.canUseActivityOptionsLaunchBounds(
1799                    options, options.getLaunchStackId())) {
1800                newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
1801            }
1802        }
1803        return newBounds;
1804    }
1805
1806    void setWindowManager(WindowManagerService wm) {
1807        mWindowManager = wm;
1808    }
1809
1810    void removePendingActivityLaunchesLocked(ActivityStack stack) {
1811        for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
1812            PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
1813            if (pal.stack == stack) {
1814                mPendingActivityLaunches.remove(palNdx);
1815            }
1816        }
1817    }
1818}
1819