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