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