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_ABORTED;
21import static android.app.ActivityManager.START_CANCELED;
22import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
23import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
24import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
25import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
26import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
27import static android.app.ActivityManager.START_SUCCESS;
28import static android.app.ActivityManager.START_TASK_TO_FRONT;
29import static android.app.ActivityManager.StackId;
30import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
31import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
32import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
33import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
34import static android.app.ActivityManager.StackId.HOME_STACK_ID;
35import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
36import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
37import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
38import static android.app.ActivityManager.StackId.isDynamicStack;
39import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
40import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
41import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
42import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
43import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
44import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
45import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
46import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
47import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
48import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
49import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
50import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
51import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
52import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
53import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
54import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
55import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
56import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
57import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
58import static android.view.Display.DEFAULT_DISPLAY;
59import static android.view.Display.INVALID_DISPLAY;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
62import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
63import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
65import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
66import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
67import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
70import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
71import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
72import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
73import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
74import static com.android.server.am.ActivityManagerService.ANIMATE;
75import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
76import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
77import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
78import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
79import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
80import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
81import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
82import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
83import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
84import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
85import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
86import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
87import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
88
89import android.annotation.NonNull;
90import android.app.ActivityManager;
91import android.app.ActivityOptions;
92import android.app.AppGlobals;
93import android.app.IApplicationThread;
94import android.app.PendingIntent;
95import android.app.ProfilerInfo;
96import android.app.WaitResult;
97import android.content.IIntentSender;
98import android.content.Intent;
99import android.content.IntentSender;
100import android.content.pm.ActivityInfo;
101import android.content.pm.ApplicationInfo;
102import android.content.pm.AuxiliaryResolveInfo;
103import android.content.pm.PackageManager;
104import android.content.pm.ResolveInfo;
105import android.content.pm.UserInfo;
106import android.content.res.Configuration;
107import android.graphics.Rect;
108import android.hardware.power.V1_0.PowerHint;
109import android.os.Binder;
110import android.os.Bundle;
111import android.os.IBinder;
112import android.os.RemoteException;
113import android.os.SystemClock;
114import android.os.UserHandle;
115import android.os.UserManager;
116import android.service.voice.IVoiceInteractionSession;
117import android.text.TextUtils;
118import android.util.EventLog;
119import android.util.Slog;
120
121import com.android.internal.app.HeavyWeightSwitcherActivity;
122import com.android.internal.app.IVoiceInteractor;
123import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
124import com.android.server.pm.InstantAppResolver;
125import com.android.server.wm.WindowManagerService;
126
127import java.io.PrintWriter;
128import java.text.DateFormat;
129import java.util.ArrayList;
130import java.util.Date;
131
132/**
133 * Controller for interpreting how and then launching activities.
134 *
135 * This class collects all the logic for determining how an intent and flags should be turned into
136 * an activity and associated task and stack.
137 */
138class ActivityStarter {
139    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
140    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
141    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
142    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
143    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
144
145    private final ActivityManagerService mService;
146    private final ActivityStackSupervisor mSupervisor;
147    private ActivityStartInterceptor mInterceptor;
148    private WindowManagerService mWindowManager;
149
150    final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
151
152    // Share state variable among methods when starting an activity.
153    private ActivityRecord mStartActivity;
154    private Intent mIntent;
155    private int mCallingUid;
156    private ActivityOptions mOptions;
157
158    private boolean mLaunchSingleTop;
159    private boolean mLaunchSingleInstance;
160    private boolean mLaunchSingleTask;
161    private boolean mLaunchTaskBehind;
162    private int mLaunchFlags;
163
164    private Rect mLaunchBounds;
165
166    private ActivityRecord mNotTop;
167    private boolean mDoResume;
168    private int mStartFlags;
169    private ActivityRecord mSourceRecord;
170    private int mSourceDisplayId;
171
172    private TaskRecord mInTask;
173    private boolean mAddingToTask;
174    private TaskRecord mReuseTask;
175
176    private ActivityInfo mNewTaskInfo;
177    private Intent mNewTaskIntent;
178    private ActivityStack mSourceStack;
179    private ActivityStack mTargetStack;
180    // Indicates that we moved other task and are going to put something on top soon, so
181    // we don't want to show it redundantly or accidentally change what's shown below.
182    private boolean mMovedOtherTask;
183    private boolean mMovedToFront;
184    private boolean mNoAnimation;
185    private boolean mKeepCurTransition;
186    private boolean mAvoidMoveToFront;
187    private boolean mPowerHintSent;
188
189    // We must track when we deliver the new intent since multiple code paths invoke
190    // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
191    // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
192    // delivered at most once.
193    private boolean mIntentDelivered;
194
195    private IVoiceInteractionSession mVoiceSession;
196    private IVoiceInteractor mVoiceInteractor;
197
198    private boolean mUsingVr2dDisplay;
199
200    // Last home activity record we attempted to start
201    private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
202    // The result of the last home activity we attempted to start.
203    private int mLastHomeActivityStartResult;
204    // Last activity record we attempted to start
205    private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
206    // The result of the last activity we attempted to start.
207    private int mLastStartActivityResult;
208    // Time in milli seconds we attempted to start the last activity.
209    private long mLastStartActivityTimeMs;
210    // The reason we were trying to start the last activity
211    private String mLastStartReason;
212
213    private void reset() {
214        mStartActivity = null;
215        mIntent = null;
216        mCallingUid = -1;
217        mOptions = null;
218
219        mLaunchSingleTop = false;
220        mLaunchSingleInstance = false;
221        mLaunchSingleTask = false;
222        mLaunchTaskBehind = false;
223        mLaunchFlags = 0;
224
225        mLaunchBounds = null;
226
227        mNotTop = null;
228        mDoResume = false;
229        mStartFlags = 0;
230        mSourceRecord = null;
231        mSourceDisplayId = INVALID_DISPLAY;
232
233        mInTask = null;
234        mAddingToTask = false;
235        mReuseTask = null;
236
237        mNewTaskInfo = null;
238        mNewTaskIntent = null;
239        mSourceStack = null;
240
241        mTargetStack = null;
242        mMovedOtherTask = false;
243        mMovedToFront = false;
244        mNoAnimation = false;
245        mKeepCurTransition = false;
246        mAvoidMoveToFront = false;
247
248        mVoiceSession = null;
249        mVoiceInteractor = null;
250
251        mUsingVr2dDisplay = false;
252
253        mIntentDelivered = false;
254    }
255
256    ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
257        mService = service;
258        mSupervisor = supervisor;
259        mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
260        mUsingVr2dDisplay = false;
261    }
262
263    int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
264            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
265            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
266            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
267            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
268            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
269            ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
270
271        if (TextUtils.isEmpty(reason)) {
272            throw new IllegalArgumentException("Need to specify a reason.");
273        }
274        mLastStartReason = reason;
275        mLastStartActivityTimeMs = System.currentTimeMillis();
276        mLastStartActivityRecord[0] = null;
277
278        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
279                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
280                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
281                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
282                inTask);
283
284        if (outActivity != null) {
285            // mLastStartActivityRecord[0] is set in the call to startActivity above.
286            outActivity[0] = mLastStartActivityRecord[0];
287        }
288
289        // Aborted results are treated as successes externally, but we must track them internally.
290        return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
291    }
292
293    /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
294    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
295            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
296            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
297            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
298            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
299            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
300            ActivityRecord[] outActivity, TaskRecord inTask) {
301        int err = ActivityManager.START_SUCCESS;
302        // Pull the optional Ephemeral Installer-only bundle out of the options early.
303        final Bundle verificationBundle
304                = options != null ? options.popAppVerificationBundle() : null;
305
306        ProcessRecord callerApp = null;
307        if (caller != null) {
308            callerApp = mService.getRecordForAppLocked(caller);
309            if (callerApp != null) {
310                callingPid = callerApp.pid;
311                callingUid = callerApp.info.uid;
312            } else {
313                Slog.w(TAG, "Unable to find app for caller " + caller
314                        + " (pid=" + callingPid + ") when starting: "
315                        + intent.toString());
316                err = ActivityManager.START_PERMISSION_DENIED;
317            }
318        }
319
320        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
321
322        if (err == ActivityManager.START_SUCCESS) {
323            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
324                    + "} from uid " + callingUid);
325        }
326
327        ActivityRecord sourceRecord = null;
328        ActivityRecord resultRecord = null;
329        if (resultTo != null) {
330            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
331            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
332                    "Will send result to " + resultTo + " " + sourceRecord);
333            if (sourceRecord != null) {
334                if (requestCode >= 0 && !sourceRecord.finishing) {
335                    resultRecord = sourceRecord;
336                }
337            }
338        }
339
340        final int launchFlags = intent.getFlags();
341
342        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
343            // Transfer the result target from the source activity to the new
344            // one being started, including any failures.
345            if (requestCode >= 0) {
346                ActivityOptions.abort(options);
347                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
348            }
349            resultRecord = sourceRecord.resultTo;
350            if (resultRecord != null && !resultRecord.isInStackLocked()) {
351                resultRecord = null;
352            }
353            resultWho = sourceRecord.resultWho;
354            requestCode = sourceRecord.requestCode;
355            sourceRecord.resultTo = null;
356            if (resultRecord != null) {
357                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
358            }
359            if (sourceRecord.launchedFromUid == callingUid) {
360                // The new activity is being launched from the same uid as the previous
361                // activity in the flow, and asking to forward its result back to the
362                // previous.  In this case the activity is serving as a trampoline between
363                // the two, so we also want to update its launchedFromPackage to be the
364                // same as the previous activity.  Note that this is safe, since we know
365                // these two packages come from the same uid; the caller could just as
366                // well have supplied that same package name itself.  This specifially
367                // deals with the case of an intent picker/chooser being launched in the app
368                // flow to redirect to an activity picked by the user, where we want the final
369                // activity to consider it to have been launched by the previous app activity.
370                callingPackage = sourceRecord.launchedFromPackage;
371            }
372        }
373
374        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
375            // We couldn't find a class that can handle the given Intent.
376            // That's the end of that!
377            err = ActivityManager.START_INTENT_NOT_RESOLVED;
378        }
379
380        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
381            // We couldn't find the specific class specified in the Intent.
382            // Also the end of the line.
383            err = ActivityManager.START_CLASS_NOT_FOUND;
384        }
385
386        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
387                && sourceRecord.getTask().voiceSession != null) {
388            // If this activity is being launched as part of a voice session, we need
389            // to ensure that it is safe to do so.  If the upcoming activity will also
390            // be part of the voice session, we can only launch it if it has explicitly
391            // said it supports the VOICE category, or it is a part of the calling app.
392            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
393                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
394                try {
395                    intent.addCategory(Intent.CATEGORY_VOICE);
396                    if (!AppGlobals.getPackageManager().activitySupportsIntent(
397                            intent.getComponent(), intent, resolvedType)) {
398                        Slog.w(TAG,
399                                "Activity being started in current voice task does not support voice: "
400                                        + intent);
401                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
402                    }
403                } catch (RemoteException e) {
404                    Slog.w(TAG, "Failure checking voice capabilities", e);
405                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
406                }
407            }
408        }
409
410        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
411            // If the caller is starting a new voice session, just make sure the target
412            // is actually allowing it to run this way.
413            try {
414                if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
415                        intent, resolvedType)) {
416                    Slog.w(TAG,
417                            "Activity being started in new voice task does not support: "
418                                    + intent);
419                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
420                }
421            } catch (RemoteException e) {
422                Slog.w(TAG, "Failure checking voice capabilities", e);
423                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
424            }
425        }
426
427        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
428
429        if (err != START_SUCCESS) {
430            if (resultRecord != null) {
431                resultStack.sendActivityResultLocked(
432                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
433            }
434            ActivityOptions.abort(options);
435            return err;
436        }
437
438        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
439                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
440                resultRecord, resultStack, options);
441        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
442                callingPid, resolvedType, aInfo.applicationInfo);
443
444        if (mService.mController != null) {
445            try {
446                // The Intent we give to the watcher has the extra data
447                // stripped off, since it can contain private information.
448                Intent watchIntent = intent.cloneFilter();
449                abort |= !mService.mController.activityStarting(watchIntent,
450                        aInfo.applicationInfo.packageName);
451            } catch (RemoteException e) {
452                mService.mController = null;
453            }
454        }
455
456        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
457        mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
458                options);
459        intent = mInterceptor.mIntent;
460        rInfo = mInterceptor.mRInfo;
461        aInfo = mInterceptor.mAInfo;
462        resolvedType = mInterceptor.mResolvedType;
463        inTask = mInterceptor.mInTask;
464        callingPid = mInterceptor.mCallingPid;
465        callingUid = mInterceptor.mCallingUid;
466        options = mInterceptor.mActivityOptions;
467        if (abort) {
468            if (resultRecord != null) {
469                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
470                        RESULT_CANCELED, null);
471            }
472            // We pretend to the caller that it was really started, but
473            // they will just get a cancel result.
474            ActivityOptions.abort(options);
475            return START_ABORTED;
476        }
477
478        // If permissions need a review before any of the app components can run, we
479        // launch the review activity and pass a pending intent to start the activity
480        // we are to launching now after the review is completed.
481        if (mService.mPermissionReviewRequired && aInfo != null) {
482            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
483                    aInfo.packageName, userId)) {
484                IIntentSender target = mService.getIntentSenderLocked(
485                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
486                        callingUid, userId, null, null, 0, new Intent[]{intent},
487                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
488                                | PendingIntent.FLAG_ONE_SHOT, null);
489
490                final int flags = intent.getFlags();
491                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
492                newIntent.setFlags(flags
493                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
494                newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
495                newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
496                if (resultRecord != null) {
497                    newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
498                }
499                intent = newIntent;
500
501                resolvedType = null;
502                callingUid = realCallingUid;
503                callingPid = realCallingPid;
504
505                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
506                aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
507                        null /*profilerInfo*/);
508
509                if (DEBUG_PERMISSIONS_REVIEW) {
510                    Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
511                            true, false) + "} from uid " + callingUid + " on display "
512                            + (mSupervisor.mFocusedStack == null
513                            ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
514                }
515            }
516        }
517
518        // If we have an ephemeral app, abort the process of launching the resolved intent.
519        // Instead, launch the ephemeral installer. Once the installer is finished, it
520        // starts either the intent we resolved here [on install error] or the ephemeral
521        // app [on install success].
522        if (rInfo != null && rInfo.auxiliaryInfo != null) {
523            intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
524                    callingPackage, verificationBundle, resolvedType, userId);
525            resolvedType = null;
526            callingUid = realCallingUid;
527            callingPid = realCallingPid;
528
529            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
530        }
531
532        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
533                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
534                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
535                mSupervisor, options, sourceRecord);
536        if (outActivity != null) {
537            outActivity[0] = r;
538        }
539
540        if (r.appTimeTracker == null && sourceRecord != null) {
541            // If the caller didn't specify an explicit time tracker, we want to continue
542            // tracking under any it has.
543            r.appTimeTracker = sourceRecord.appTimeTracker;
544        }
545
546        final ActivityStack stack = mSupervisor.mFocusedStack;
547        if (voiceSession == null && (stack.mResumedActivity == null
548                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
549            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
550                    realCallingPid, realCallingUid, "Activity start")) {
551                PendingActivityLaunch pal =  new PendingActivityLaunch(r,
552                        sourceRecord, startFlags, stack, callerApp);
553                mPendingActivityLaunches.add(pal);
554                ActivityOptions.abort(options);
555                return ActivityManager.START_SWITCHES_CANCELED;
556            }
557        }
558
559        if (mService.mDidAppSwitch) {
560            // This is the second allowed switch since we stopped switches,
561            // so now just generally allow switches.  Use case: user presses
562            // home (switches disabled, switch to home, mDidAppSwitch now true);
563            // user taps a home icon (coming from home so allowed, we hit here
564            // and now allow anyone to switch again).
565            mService.mAppSwitchesAllowedTime = 0;
566        } else {
567            mService.mDidAppSwitch = true;
568        }
569
570        doPendingActivityLaunchesLocked(false);
571
572        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
573                options, inTask, outActivity);
574    }
575
576    /**
577     * Creates a launch intent for the given auxiliary resolution data.
578     */
579    private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
580            Intent originalIntent, String callingPackage, Bundle verificationBundle,
581            String resolvedType, int userId) {
582        if (auxiliaryResponse.needsPhaseTwo) {
583            // request phase two resolution
584            mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
585                    auxiliaryResponse, originalIntent, resolvedType, callingPackage,
586                    verificationBundle, userId);
587        }
588        return InstantAppResolver.buildEphemeralInstallerIntent(
589                Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
590                auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
591                resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
592                auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode,
593                auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
594    }
595
596    void postStartActivityProcessing(
597            ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
598            ActivityStack targetStack) {
599
600        if (ActivityManager.isStartResultFatalError(result)) {
601            return;
602        }
603
604        // We're waiting for an activity launch to finish, but that activity simply
605        // brought another activity to front. Let startActivityMayWait() know about
606        // this, so it waits for the new activity to become visible instead.
607        if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
608            mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
609        }
610
611        int startedActivityStackId = INVALID_STACK_ID;
612        final ActivityStack currentStack = r.getStack();
613        if (currentStack != null) {
614            startedActivityStackId = currentStack.mStackId;
615        } else if (mTargetStack != null) {
616            startedActivityStackId = targetStack.mStackId;
617        }
618
619        if (startedActivityStackId == DOCKED_STACK_ID) {
620            final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
621            final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
622            if (homeStackVisible) {
623                // We launch an activity while being in home stack, which means either launcher or
624                // recents into docked stack. We don't want the launched activity to be alone in a
625                // docked stack, so we want to immediately launch recents too.
626                if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
627                mWindowManager.showRecentApps(true /* fromHome */);
628            }
629            return;
630        }
631
632        boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
633                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
634        if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
635                || result == START_DELIVERED_TO_TOP || clearedTask)) {
636            // The activity was already running in the pinned stack so it wasn't started, but either
637            // brought to the front or the new intent was delivered to it since it was already in
638            // front. Notify anyone interested in this piece of information.
639            mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
640                    clearedTask);
641            return;
642        }
643    }
644
645    void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
646        mSupervisor.moveHomeStackTaskToTop(reason);
647        mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
648                null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
649                null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
650                null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
651                null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
652                0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
653                false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
654                null /*inTask*/, "startHomeActivity: " + reason);
655        if (mSupervisor.inResumeTopActivity) {
656            // If we are in resume section already, home activity will be initialized, but not
657            // resumed (to avoid recursive resume) and will stay that way until something pokes it
658            // again. We need to schedule another resume.
659            mSupervisor.scheduleResumeTopActivities();
660        }
661    }
662
663    void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
664        intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
665                FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
666                FLAG_ACTIVITY_TASK_ON_HOME);
667        ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
668                        : ActivityOptions.makeBasic());
669        options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
670        mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
671    }
672
673    final int startActivityMayWait(IApplicationThread caller, int callingUid,
674            String callingPackage, Intent intent, String resolvedType,
675            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
676            IBinder resultTo, String resultWho, int requestCode, int startFlags,
677            ProfilerInfo profilerInfo, WaitResult outResult,
678            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
679            TaskRecord inTask, String reason) {
680        // Refuse possible leaked file descriptors
681        if (intent != null && intent.hasFileDescriptors()) {
682            throw new IllegalArgumentException("File descriptors passed in Intent");
683        }
684        mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
685        boolean componentSpecified = intent.getComponent() != null;
686
687        // Save a copy in case ephemeral needs it
688        final Intent ephemeralIntent = new Intent(intent);
689        // Don't modify the client's object!
690        intent = new Intent(intent);
691        if (componentSpecified
692                && intent.getData() != null
693                && Intent.ACTION_VIEW.equals(intent.getAction())
694                && mService.getPackageManagerInternalLocked()
695                        .isInstantAppInstallerComponent(intent.getComponent())) {
696            // intercept intents targeted directly to the ephemeral installer the
697            // ephemeral installer should never be started with a raw URL; instead
698            // adjust the intent so it looks like a "normal" instant app launch
699            intent.setComponent(null /*component*/);
700            componentSpecified = false;
701        }
702
703        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
704        if (rInfo == null) {
705            UserInfo userInfo = mSupervisor.getUserInfo(userId);
706            if (userInfo != null && userInfo.isManagedProfile()) {
707                // Special case for managed profiles, if attempting to launch non-cryto aware
708                // app in a locked managed profile from an unlocked parent allow it to resolve
709                // as user will be sent via confirm credentials to unlock the profile.
710                UserManager userManager = UserManager.get(mService.mContext);
711                boolean profileLockedAndParentUnlockingOrUnlocked = false;
712                long token = Binder.clearCallingIdentity();
713                try {
714                    UserInfo parent = userManager.getProfileParent(userId);
715                    profileLockedAndParentUnlockingOrUnlocked = (parent != null)
716                            && userManager.isUserUnlockingOrUnlocked(parent.id)
717                            && !userManager.isUserUnlockingOrUnlocked(userId);
718                } finally {
719                    Binder.restoreCallingIdentity(token);
720                }
721                if (profileLockedAndParentUnlockingOrUnlocked) {
722                    rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
723                            PackageManager.MATCH_DIRECT_BOOT_AWARE
724                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
725                }
726            }
727        }
728        // Collect information about the target of the Intent.
729        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
730
731        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
732        synchronized (mService) {
733            final int realCallingPid = Binder.getCallingPid();
734            final int realCallingUid = Binder.getCallingUid();
735            int callingPid;
736            if (callingUid >= 0) {
737                callingPid = -1;
738            } else if (caller == null) {
739                callingPid = realCallingPid;
740                callingUid = realCallingUid;
741            } else {
742                callingPid = callingUid = -1;
743            }
744
745            final ActivityStack stack = mSupervisor.mFocusedStack;
746            stack.mConfigWillChange = globalConfig != null
747                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
748            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
749                    "Starting activity when config will change = " + stack.mConfigWillChange);
750
751            final long origId = Binder.clearCallingIdentity();
752
753            if (aInfo != null &&
754                    (aInfo.applicationInfo.privateFlags
755                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
756                // This may be a heavy-weight process!  Check to see if we already
757                // have another, different heavy-weight process running.
758                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
759                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
760                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
761                            || !heavy.processName.equals(aInfo.processName))) {
762                        int appCallingUid = callingUid;
763                        if (caller != null) {
764                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
765                            if (callerApp != null) {
766                                appCallingUid = callerApp.info.uid;
767                            } else {
768                                Slog.w(TAG, "Unable to find app for caller " + caller
769                                        + " (pid=" + callingPid + ") when starting: "
770                                        + intent.toString());
771                                ActivityOptions.abort(options);
772                                return ActivityManager.START_PERMISSION_DENIED;
773                            }
774                        }
775
776                        IIntentSender target = mService.getIntentSenderLocked(
777                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
778                                appCallingUid, userId, null, null, 0, new Intent[] { intent },
779                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
780                                        | PendingIntent.FLAG_ONE_SHOT, null);
781
782                        Intent newIntent = new Intent();
783                        if (requestCode >= 0) {
784                            // Caller is requesting a result.
785                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
786                        }
787                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
788                                new IntentSender(target));
789                        if (heavy.activities.size() > 0) {
790                            ActivityRecord hist = heavy.activities.get(0);
791                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
792                                    hist.packageName);
793                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
794                                    hist.getTask().taskId);
795                        }
796                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
797                                aInfo.packageName);
798                        newIntent.setFlags(intent.getFlags());
799                        newIntent.setClassName("android",
800                                HeavyWeightSwitcherActivity.class.getName());
801                        intent = newIntent;
802                        resolvedType = null;
803                        caller = null;
804                        callingUid = Binder.getCallingUid();
805                        callingPid = Binder.getCallingPid();
806                        componentSpecified = true;
807                        rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
808                        aInfo = rInfo != null ? rInfo.activityInfo : null;
809                        if (aInfo != null) {
810                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
811                        }
812                    }
813                }
814            }
815
816            final ActivityRecord[] outRecord = new ActivityRecord[1];
817            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
818                    aInfo, rInfo, voiceSession, voiceInteractor,
819                    resultTo, resultWho, requestCode, callingPid,
820                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
821                    options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
822                    reason);
823
824            Binder.restoreCallingIdentity(origId);
825
826            if (stack.mConfigWillChange) {
827                // If the caller also wants to switch to a new configuration,
828                // do so now.  This allows a clean switch, as we are waiting
829                // for the current activity to pause (so we will not destroy
830                // it), and have not yet started the next activity.
831                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
832                        "updateConfiguration()");
833                stack.mConfigWillChange = false;
834                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
835                        "Updating to new configuration after starting activity.");
836                mService.updateConfigurationLocked(globalConfig, null, false);
837            }
838
839            if (outResult != null) {
840                outResult.result = res;
841                if (res == ActivityManager.START_SUCCESS) {
842                    mSupervisor.mWaitingActivityLaunched.add(outResult);
843                    do {
844                        try {
845                            mService.wait();
846                        } catch (InterruptedException e) {
847                        }
848                    } while (outResult.result != START_TASK_TO_FRONT
849                            && !outResult.timeout && outResult.who == null);
850                    if (outResult.result == START_TASK_TO_FRONT) {
851                        res = START_TASK_TO_FRONT;
852                    }
853                }
854                if (res == START_TASK_TO_FRONT) {
855                    final ActivityRecord r = outRecord[0];
856
857                    // ActivityRecord may represent a different activity, but it should not be in
858                    // the resumed state.
859                    if (r.nowVisible && r.state == RESUMED) {
860                        outResult.timeout = false;
861                        outResult.who = r.realActivity;
862                        outResult.totalTime = 0;
863                        outResult.thisTime = 0;
864                    } else {
865                        outResult.thisTime = SystemClock.uptimeMillis();
866                        mSupervisor.waitActivityVisible(r.realActivity, outResult);
867                        // Note: the timeout variable is not currently not ever set.
868                        do {
869                            try {
870                                mService.wait();
871                            } catch (InterruptedException e) {
872                            }
873                        } while (!outResult.timeout && outResult.who == null);
874                    }
875                }
876            }
877
878            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
879            return res;
880        }
881    }
882
883    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
884            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
885            Bundle bOptions, int userId, String reason) {
886        if (intents == null) {
887            throw new NullPointerException("intents is null");
888        }
889        if (resolvedTypes == null) {
890            throw new NullPointerException("resolvedTypes is null");
891        }
892        if (intents.length != resolvedTypes.length) {
893            throw new IllegalArgumentException("intents are length different than resolvedTypes");
894        }
895
896        final int realCallingPid = Binder.getCallingPid();
897        final int realCallingUid = Binder.getCallingUid();
898
899        int callingPid;
900        if (callingUid >= 0) {
901            callingPid = -1;
902        } else if (caller == null) {
903            callingPid = realCallingPid;
904            callingUid = realCallingUid;
905        } else {
906            callingPid = callingUid = -1;
907        }
908        final long origId = Binder.clearCallingIdentity();
909        try {
910            synchronized (mService) {
911                ActivityRecord[] outActivity = new ActivityRecord[1];
912                for (int i=0; i<intents.length; i++) {
913                    Intent intent = intents[i];
914                    if (intent == null) {
915                        continue;
916                    }
917
918                    // Refuse possible leaked file descriptors
919                    if (intent != null && intent.hasFileDescriptors()) {
920                        throw new IllegalArgumentException("File descriptors passed in Intent");
921                    }
922
923                    boolean componentSpecified = intent.getComponent() != null;
924
925                    // Don't modify the client's object!
926                    intent = new Intent(intent);
927
928                    // Collect information about the target of the Intent.
929                    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
930                            null, userId);
931                    // TODO: New, check if this is correct
932                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
933
934                    if (aInfo != null &&
935                            (aInfo.applicationInfo.privateFlags
936                                    & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
937                        throw new IllegalArgumentException(
938                                "FLAG_CANT_SAVE_STATE not supported here");
939                    }
940
941                    ActivityOptions options = ActivityOptions.fromBundle(
942                            i == intents.length - 1 ? bOptions : null);
943                    int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
944                            resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
945                            callingPid, callingUid, callingPackage,
946                            realCallingPid, realCallingUid, 0,
947                            options, false, componentSpecified, outActivity, null, reason);
948                    if (res < 0) {
949                        return res;
950                    }
951
952                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
953                }
954            }
955        } finally {
956            Binder.restoreCallingIdentity(origId);
957        }
958
959        return START_SUCCESS;
960    }
961
962    void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
963        boolean sendHint = forceSend;
964
965        if (!sendHint) {
966            // If not forced, send power hint when the activity's process is different than the
967            // current resumed activity.
968            final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
969            sendHint = resumedActivity == null
970                || resumedActivity.app == null
971                || !resumedActivity.app.equals(targetActivity.app);
972        }
973
974        if (sendHint && mService.mLocalPowerManager != null) {
975            mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
976            mPowerHintSent = true;
977        }
978    }
979
980    void sendPowerHintForLaunchEndIfNeeded() {
981        // Trigger launch power hint if activity is launched
982        if (mPowerHintSent && mService.mLocalPowerManager != null) {
983            mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
984            mPowerHintSent = false;
985        }
986    }
987
988    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
989            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
990            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
991            ActivityRecord[] outActivity) {
992        int result = START_CANCELED;
993        try {
994            mService.mWindowManager.deferSurfaceLayout();
995            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
996                    startFlags, doResume, options, inTask, outActivity);
997        } finally {
998            // If we are not able to proceed, disassociate the activity from the task. Leaving an
999            // activity in an incomplete state can lead to issues, such as performing operations
1000            // without a window container.
1001            if (!ActivityManager.isStartResultSuccessful(result)
1002                    && mStartActivity.getTask() != null) {
1003                mStartActivity.getTask().removeActivity(mStartActivity);
1004            }
1005            mService.mWindowManager.continueSurfaceLayout();
1006        }
1007
1008        postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
1009                mTargetStack);
1010
1011        return result;
1012    }
1013
1014    // Note: This method should only be called from {@link startActivity}.
1015    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1016            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1017            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1018            ActivityRecord[] outActivity) {
1019
1020        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1021                voiceInteractor);
1022
1023        computeLaunchingTaskFlags();
1024
1025        computeSourceStack();
1026
1027        mIntent.setFlags(mLaunchFlags);
1028
1029        ActivityRecord reusedActivity = getReusableIntentActivity();
1030
1031        final int preferredLaunchStackId =
1032                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1033        final int preferredLaunchDisplayId =
1034                (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
1035
1036        if (reusedActivity != null) {
1037            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1038            // still needs to be a lock task mode violation since the task gets cleared out and
1039            // the device would otherwise leave the locked task.
1040            if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
1041                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1042                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1043                mSupervisor.showLockTaskToast();
1044                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1045                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1046            }
1047
1048            if (mStartActivity.getTask() == null) {
1049                mStartActivity.setTask(reusedActivity.getTask());
1050            }
1051            if (reusedActivity.getTask().intent == null) {
1052                // This task was started because of movement of the activity based on affinity...
1053                // Now that we are actually launching it, we can assign the base intent.
1054                reusedActivity.getTask().setIntent(mStartActivity);
1055            }
1056
1057            // This code path leads to delivering a new intent, we want to make sure we schedule it
1058            // as the first operation, in case the activity will be resumed as a result of later
1059            // operations.
1060            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1061                    || isDocumentLaunchesIntoExisting(mLaunchFlags)
1062                    || mLaunchSingleInstance || mLaunchSingleTask) {
1063                final TaskRecord task = reusedActivity.getTask();
1064
1065                // In this situation we want to remove all activities from the task up to the one
1066                // being started. In most cases this means we are resetting the task to its initial
1067                // state.
1068                final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1069                        mLaunchFlags);
1070
1071                // The above code can remove {@code reusedActivity} from the task, leading to the
1072                // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1073                // task reference is needed in the call below to
1074                // {@link setTargetStackAndMoveToFrontIfNeeded}.
1075                if (reusedActivity.getTask() == null) {
1076                    reusedActivity.setTask(task);
1077                }
1078
1079                if (top != null) {
1080                    if (top.frontOfTask) {
1081                        // Activity aliases may mean we use different intents for the top activity,
1082                        // so make sure the task now has the identity of the new intent.
1083                        top.getTask().setIntent(mStartActivity);
1084                    }
1085                    deliverNewIntent(top);
1086                }
1087            }
1088
1089            sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
1090
1091            reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
1092
1093            final ActivityRecord outResult =
1094                    outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1095
1096            // When there is a reused activity and the current result is a trampoline activity,
1097            // set the reused activity as the result.
1098            if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1099                outActivity[0] = reusedActivity;
1100            }
1101
1102            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1103                // We don't need to start a new activity, and the client said not to do anything
1104                // if that is the case, so this is it!  And for paranoia, make sure we have
1105                // correctly resumed the top activity.
1106                resumeTargetStackIfNeeded();
1107                return START_RETURN_INTENT_TO_CALLER;
1108            }
1109            setTaskFromIntentActivity(reusedActivity);
1110
1111            if (!mAddingToTask && mReuseTask == null) {
1112                // We didn't do anything...  but it was needed (a.k.a., client don't use that
1113                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
1114                resumeTargetStackIfNeeded();
1115                if (outActivity != null && outActivity.length > 0) {
1116                    outActivity[0] = reusedActivity;
1117                }
1118
1119                return START_TASK_TO_FRONT;
1120            }
1121        }
1122
1123        if (mStartActivity.packageName == null) {
1124            final ActivityStack sourceStack = mStartActivity.resultTo != null
1125                    ? mStartActivity.resultTo.getStack() : null;
1126            if (sourceStack != null) {
1127                sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1128                        mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1129                        null /* data */);
1130            }
1131            ActivityOptions.abort(mOptions);
1132            return START_CLASS_NOT_FOUND;
1133        }
1134
1135        // If the activity being launched is the same as the one currently at the top, then
1136        // we need to check if it should only be launched once.
1137        final ActivityStack topStack = mSupervisor.mFocusedStack;
1138        final ActivityRecord topFocused = topStack.topActivity();
1139        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1140        final boolean dontStart = top != null && mStartActivity.resultTo == null
1141                && top.realActivity.equals(mStartActivity.realActivity)
1142                && top.userId == mStartActivity.userId
1143                && top.app != null && top.app.thread != null
1144                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1145                || mLaunchSingleTop || mLaunchSingleTask);
1146        if (dontStart) {
1147            // For paranoia, make sure we have correctly resumed the top activity.
1148            topStack.mLastPausedActivity = null;
1149            if (mDoResume) {
1150                mSupervisor.resumeFocusedStackTopActivityLocked();
1151            }
1152            ActivityOptions.abort(mOptions);
1153            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1154                // We don't need to start a new activity, and the client said not to do
1155                // anything if that is the case, so this is it!
1156                return START_RETURN_INTENT_TO_CALLER;
1157            }
1158
1159            deliverNewIntent(top);
1160
1161            // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1162            // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1163            mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
1164                    preferredLaunchDisplayId, topStack.mStackId);
1165
1166            return START_DELIVERED_TO_TOP;
1167        }
1168
1169        boolean newTask = false;
1170        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1171                ? mSourceRecord.getTask() : null;
1172
1173        // Should this be considered a new task?
1174        int result = START_SUCCESS;
1175        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1176                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1177            newTask = true;
1178            result = setTaskFromReuseOrCreateNewTask(
1179                    taskToAffiliate, preferredLaunchStackId, topStack);
1180        } else if (mSourceRecord != null) {
1181            result = setTaskFromSourceRecord();
1182        } else if (mInTask != null) {
1183            result = setTaskFromInTask();
1184        } else {
1185            // This not being started from an existing activity, and not part of a new task...
1186            // just put it in the top task, though these days this case should never happen.
1187            setTaskToCurrentTopOrCreateNewTask();
1188        }
1189        if (result != START_SUCCESS) {
1190            return result;
1191        }
1192
1193        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1194                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1195        mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1196                mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
1197        if (mSourceRecord != null) {
1198            mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
1199        }
1200        if (newTask) {
1201            EventLog.writeEvent(
1202                    EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1203                    mStartActivity.getTask().taskId);
1204        }
1205        ActivityStack.logStartActivity(
1206                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
1207        mTargetStack.mLastPausedActivity = null;
1208
1209        sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
1210
1211        mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1212                mOptions);
1213        if (mDoResume) {
1214            final ActivityRecord topTaskActivity =
1215                    mStartActivity.getTask().topRunningActivityLocked();
1216            if (!mTargetStack.isFocusable()
1217                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1218                    && mStartActivity != topTaskActivity)) {
1219                // If the activity is not focusable, we can't resume it, but still would like to
1220                // make sure it becomes visible as it starts (this will also trigger entry
1221                // animation). An example of this are PIP activities.
1222                // Also, we don't want to resume activities in a task that currently has an overlay
1223                // as the starting activity just needs to be in the visible paused state until the
1224                // over is removed.
1225                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1226                // Go ahead and tell window manager to execute app transition for this activity
1227                // since the app transition will not be triggered through the resume channel.
1228                mWindowManager.executeAppTransition();
1229            } else {
1230                // If the target stack was not previously focusable (previous top running activity
1231                // on that stack was not visible) then any prior calls to move the stack to the
1232                // will not update the focused stack.  If starting the new activity now allows the
1233                // task stack to be focusable, then ensure that we now update the focused stack
1234                // accordingly.
1235                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1236                    mTargetStack.moveToFront("startActivityUnchecked");
1237                }
1238                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1239                        mOptions);
1240            }
1241        } else {
1242            mTargetStack.addRecentActivityLocked(mStartActivity);
1243        }
1244        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1245
1246        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
1247                preferredLaunchDisplayId, mTargetStack.mStackId);
1248
1249        return START_SUCCESS;
1250    }
1251
1252    private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1253            boolean doResume, int startFlags, ActivityRecord sourceRecord,
1254            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1255        reset();
1256
1257        mStartActivity = r;
1258        mIntent = r.intent;
1259        mOptions = options;
1260        mCallingUid = r.launchedFromUid;
1261        mSourceRecord = sourceRecord;
1262        mVoiceSession = voiceSession;
1263        mVoiceInteractor = voiceInteractor;
1264
1265        mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
1266
1267        mLaunchBounds = getOverrideBounds(r, options, inTask);
1268
1269        mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1270        mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1271        mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1272        mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1273                r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1274        mLaunchTaskBehind = r.mLaunchTaskBehind
1275                && !mLaunchSingleTask && !mLaunchSingleInstance
1276                && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1277
1278        sendNewTaskResultRequestIfNeeded();
1279
1280        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1281            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1282        }
1283
1284        // If we are actually going to launch in to a new task, there are some cases where
1285        // we further want to do multiple task.
1286        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1287            if (mLaunchTaskBehind
1288                    || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1289                mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1290            }
1291        }
1292
1293        // We'll invoke onUserLeaving before onPause only if the launching
1294        // activity did not explicitly state that this is an automated launch.
1295        mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1296        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1297                "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1298
1299        // If the caller has asked not to resume at this point, we make note
1300        // of this in the record so that we can skip it when trying to find
1301        // the top running activity.
1302        mDoResume = doResume;
1303        if (!doResume || !r.okToShowLocked()) {
1304            r.delayedResume = true;
1305            mDoResume = false;
1306        }
1307
1308        if (mOptions != null && mOptions.getLaunchTaskId() != -1
1309                && mOptions.getTaskOverlay()) {
1310            r.mTaskOverlay = true;
1311            if (!mOptions.canTaskOverlayResume()) {
1312                final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1313                final ActivityRecord top = task != null ? task.getTopActivity() : null;
1314                if (top != null && top.state != RESUMED) {
1315
1316                    // The caller specifies that we'd like to be avoided to be moved to the front,
1317                    // so be it!
1318                    mDoResume = false;
1319                    mAvoidMoveToFront = true;
1320                }
1321            }
1322        }
1323
1324        mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1325
1326        mInTask = inTask;
1327        // In some flows in to this function, we retrieve the task record and hold on to it
1328        // without a lock before calling back in to here...  so the task at this point may
1329        // not actually be in recents.  Check for that, and if it isn't in recents just
1330        // consider it invalid.
1331        if (inTask != null && !inTask.inRecents) {
1332            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1333            mInTask = null;
1334        }
1335
1336        mStartFlags = startFlags;
1337        // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1338        // is the same as the one making the call...  or, as a special case, if we do not know
1339        // the caller then we count the current top activity as the caller.
1340        if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1341            ActivityRecord checkedCaller = sourceRecord;
1342            if (checkedCaller == null) {
1343                checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1344                        mNotTop);
1345            }
1346            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1347                // Caller is not the same as launcher, so always needed.
1348                mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1349            }
1350        }
1351
1352        mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1353    }
1354
1355    private void sendNewTaskResultRequestIfNeeded() {
1356        final ActivityStack sourceStack = mStartActivity.resultTo != null
1357                ? mStartActivity.resultTo.getStack() : null;
1358        if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1359            // For whatever reason this activity is being launched into a new task...
1360            // yet the caller has requested a result back.  Well, that is pretty messed up,
1361            // so instead immediately send back a cancel and let the new task continue launched
1362            // as normal without a dependency on its originator.
1363            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1364            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1365                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1366                    null /* data */);
1367            mStartActivity.resultTo = null;
1368        }
1369    }
1370
1371    private void computeLaunchingTaskFlags() {
1372        // If the caller is not coming from another activity, but has given us an explicit task into
1373        // which they would like us to launch the new activity, then let's see about doing that.
1374        if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
1375            final Intent baseIntent = mInTask.getBaseIntent();
1376            final ActivityRecord root = mInTask.getRootActivity();
1377            if (baseIntent == null) {
1378                ActivityOptions.abort(mOptions);
1379                throw new IllegalArgumentException("Launching into task without base intent: "
1380                        + mInTask);
1381            }
1382
1383            // If this task is empty, then we are adding the first activity -- it
1384            // determines the root, and must be launching as a NEW_TASK.
1385            if (mLaunchSingleInstance || mLaunchSingleTask) {
1386                if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1387                    ActivityOptions.abort(mOptions);
1388                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1389                            + mStartActivity + " into different task " + mInTask);
1390                }
1391                if (root != null) {
1392                    ActivityOptions.abort(mOptions);
1393                    throw new IllegalArgumentException("Caller with mInTask " + mInTask
1394                            + " has root " + root + " but target is singleInstance/Task");
1395                }
1396            }
1397
1398            // If task is empty, then adopt the interesting intent launch flags in to the
1399            // activity being started.
1400            if (root == null) {
1401                final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1402                        | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1403                mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1404                        | (baseIntent.getFlags() & flagsOfInterest);
1405                mIntent.setFlags(mLaunchFlags);
1406                mInTask.setIntent(mStartActivity);
1407                mAddingToTask = true;
1408
1409                // If the task is not empty and the caller is asking to start it as the root of
1410                // a new task, then we don't actually want to start this on the task. We will
1411                // bring the task to the front, and possibly give it a new intent.
1412            } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1413                mAddingToTask = false;
1414
1415            } else {
1416                mAddingToTask = true;
1417            }
1418
1419            mReuseTask = mInTask;
1420        } else {
1421            mInTask = null;
1422            // Launch ResolverActivity in the source task, so that it stays in the task bounds
1423            // when in freeform workspace.
1424            // Also put noDisplay activities in the source task. These by itself can be placed
1425            // in any task/stack, however it could launch other activities like ResolverActivity,
1426            // and we want those to stay in the original task.
1427            if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1428                    && mSourceRecord.isFreeform())  {
1429                mAddingToTask = true;
1430            }
1431        }
1432
1433        if (mInTask == null) {
1434            if (mSourceRecord == null) {
1435                // This activity is not being started from another...  in this
1436                // case we -always- start a new task.
1437                if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1438                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1439                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1440                    mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1441                }
1442            } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1443                // The original activity who is starting us is running as a single
1444                // instance...  this new activity it is starting must go on its
1445                // own task.
1446                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1447            } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1448                // The activity being started is a single instance...  it always
1449                // gets launched into its own task.
1450                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1451            }
1452        }
1453    }
1454
1455    private void computeSourceStack() {
1456        if (mSourceRecord == null) {
1457            mSourceStack = null;
1458            return;
1459        }
1460        if (!mSourceRecord.finishing) {
1461            mSourceStack = mSourceRecord.getStack();
1462            return;
1463        }
1464
1465        // If the source is finishing, we can't further count it as our source. This is because the
1466        // task it is associated with may now be empty and on its way out, so we don't want to
1467        // blindly throw it in to that task.  Instead we will take the NEW_TASK flow and try to find
1468        // a task for it. But save the task information so it can be used when creating the new task.
1469        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1470            Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1471                    + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1472            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1473            mNewTaskInfo = mSourceRecord.info;
1474
1475            // It is not guaranteed that the source record will have a task associated with it. For,
1476            // example, if this method is being called for processing a pending activity launch, it
1477            // is possible that the activity has been removed from the task after the launch was
1478            // enqueued.
1479            final TaskRecord sourceTask = mSourceRecord.getTask();
1480            mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
1481        }
1482        mSourceRecord = null;
1483        mSourceStack = null;
1484    }
1485
1486    /**
1487     * Decide whether the new activity should be inserted into an existing task. Returns null
1488     * if not or an ActivityRecord with the task into which the new activity should be added.
1489     */
1490    private ActivityRecord getReusableIntentActivity() {
1491        // We may want to try to place the new activity in to an existing task.  We always
1492        // do this if the target activity is singleTask or singleInstance; we will also do
1493        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1494        // us to still place it in a new task: multi task, always doc mode, or being asked to
1495        // launch this as a new task behind the current one.
1496        boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1497                (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1498                || mLaunchSingleInstance || mLaunchSingleTask;
1499        // If bring to front is requested, and no result is requested and we have not been given
1500        // an explicit task to launch in to, and we can find a task that was started with this
1501        // same component, then instead of launching bring that one to the front.
1502        putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1503        ActivityRecord intentActivity = null;
1504        if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1505            final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1506            intentActivity = task != null ? task.getTopActivity() : null;
1507        } else if (putIntoExistingTask) {
1508            if (mLaunchSingleInstance) {
1509                // There can be one and only one instance of single instance activity in the
1510                // history, and it is always in its own unique task, so we do a special search.
1511               intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1512                       mStartActivity.isHomeActivity());
1513            } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1514                // For the launch adjacent case we only want to put the activity in an existing
1515                // task if the activity already exists in the history.
1516                intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1517                        !mLaunchSingleTask);
1518            } else {
1519                // Otherwise find the best task to put the activity in.
1520                intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
1521            }
1522        }
1523        return intentActivity;
1524    }
1525
1526    /**
1527     * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1528     * then return the Vr mode's virtual display ID. If not, if the source activity has
1529     * a explicit display ID set, use that to launch the activity.
1530     */
1531    private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
1532        // Check if the Activity is a VR activity. If so, the activity should be launched in
1533        // main display.
1534        if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1535            return DEFAULT_DISPLAY;
1536        }
1537
1538        // Get the virtual display id from ActivityManagerService.
1539        int displayId = mService.mVr2dDisplayId;
1540        if (displayId != INVALID_DISPLAY) {
1541            if (DEBUG_STACK) {
1542                Slog.d(TAG, "getSourceDisplayId :" + displayId);
1543            }
1544            mUsingVr2dDisplay = true;
1545            return displayId;
1546        }
1547
1548        displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1549        // If the activity has a displayId set explicitly, launch it on the same displayId.
1550        if (displayId != INVALID_DISPLAY) {
1551            return displayId;
1552        }
1553        return DEFAULT_DISPLAY;
1554    }
1555
1556    /**
1557     * Figure out which task and activity to bring to front when we have found an existing matching
1558     * activity record in history. May also clear the task if needed.
1559     * @param intentActivity Existing matching activity.
1560     * @return {@link ActivityRecord} brought to front.
1561     */
1562    private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1563        mTargetStack = intentActivity.getStack();
1564        mTargetStack.mLastPausedActivity = null;
1565        // If the target task is not in the front, then we need to bring it to the front...
1566        // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1567        // the same behavior as if a new instance was being started, which means not bringing it
1568        // to the front if the caller is not itself in the front.
1569        final ActivityStack focusStack = mSupervisor.getFocusedStack();
1570        ActivityRecord curTop = (focusStack == null)
1571                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1572
1573        final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1574        if (topTask != null
1575                && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
1576                && !mAvoidMoveToFront) {
1577            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1578            if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1579                    mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
1580                // We really do want to push this one into the user's face, right now.
1581                if (mLaunchTaskBehind && mSourceRecord != null) {
1582                    intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
1583                }
1584                mMovedOtherTask = true;
1585
1586                // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1587                // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1588                // So no point resuming any of the activities here, it just wastes one extra
1589                // resuming, plus enter AND exit transitions.
1590                // Here we only want to bring the target stack forward. Transition will be applied
1591                // to the new activity that's started after the old ones are gone.
1592                final boolean willClearTask =
1593                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1594                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1595                if (!willClearTask) {
1596                    final ActivityStack launchStack = getLaunchStack(
1597                            mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1598                    final TaskRecord intentTask = intentActivity.getTask();
1599                    if (launchStack == null || launchStack == mTargetStack) {
1600                        // We only want to move to the front, if we aren't going to launch on a
1601                        // different stack. If we launch on a different stack, we will put the
1602                        // task on top there.
1603                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1604                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1605                        mMovedToFront = true;
1606                    } else if (launchStack.mStackId == DOCKED_STACK_ID
1607                            || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1608                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1609                            // If we want to launch adjacent and mTargetStack is not the computed
1610                            // launch stack - move task to top of computed stack.
1611                            intentTask.reparent(launchStack.mStackId, ON_TOP,
1612                                    REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1613                                    "launchToSide");
1614                        } else {
1615                            // TODO: This should be reevaluated in MW v2.
1616                            // We choose to move task to front instead of launching it adjacent
1617                            // when specific stack was requested explicitly and it appeared to be
1618                            // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1619                            mTargetStack.moveTaskToFrontLocked(intentTask,
1620                                    mNoAnimation, mOptions, mStartActivity.appTimeTracker,
1621                                    "bringToFrontInsteadOfAdjacentLaunch");
1622                        }
1623                        mMovedToFront = true;
1624                    } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1625                        // Target and computed stacks are on different displays and we've
1626                        // found a matching task - move the existing instance to that display and
1627                        // move it to front.
1628                        intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
1629                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1630                                "reparentToDisplay");
1631                        mMovedToFront = true;
1632                    } else if (launchStack.getStackId() == StackId.HOME_STACK_ID
1633                        && mTargetStack.getStackId() != StackId.HOME_STACK_ID) {
1634                        // It is possible for the home activity to be in another stack initially.
1635                        // For example, the activity may have been initially started with an intent
1636                        // which placed it in the fullscreen stack. To ensure the proper handling of
1637                        // the activity based on home stack assumptions, we must move it over.
1638                        intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
1639                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1640                                "reparentingHome");
1641                        mMovedToFront = true;
1642                    }
1643                    mOptions = null;
1644
1645                    // We are moving a task to the front, use starting window to hide initial drawn
1646                    // delay.
1647                    intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1648                            true /* taskSwitch */);
1649                }
1650                updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
1651            }
1652        }
1653        if (!mMovedToFront && mDoResume) {
1654            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1655                    + " from " + intentActivity);
1656            mTargetStack.moveToFront("intentActivityFound");
1657        }
1658
1659        mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
1660                DEFAULT_DISPLAY, mTargetStack.mStackId);
1661
1662        // If the caller has requested that the target task be reset, then do so.
1663        if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1664            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1665        }
1666        return intentActivity;
1667    }
1668
1669    private void updateTaskReturnToType(
1670            TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1671        if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1672                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1673            // Caller wants to appear on home activity.
1674            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1675            return;
1676        } else if (focusedStack == null || focusedStack.isHomeStack()) {
1677            // Task will be launched over the home stack, so return home.
1678            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1679            return;
1680        } else if (focusedStack != null && focusedStack != task.getStack() &&
1681                focusedStack.isAssistantStack()) {
1682            // Task was launched over the assistant stack, so return there
1683            task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1684            return;
1685        }
1686
1687        // Else we are coming from an application stack so return to an application.
1688        task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1689    }
1690
1691    private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1692        if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1693                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1694            // The caller has requested to completely replace any existing task with its new
1695            // activity. Well that should not be too hard...
1696            // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1697            // removed from calling performClearTaskLocked (For example, if it is being brought out
1698            // of history or if it is finished immediately), thus disassociating the task. Also note
1699            // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1700            // launching another activity.
1701            // TODO(b/36119896):  We shouldn't trigger activity launches in this path since we are
1702            // already launching one.
1703            final TaskRecord task = intentActivity.getTask();
1704            task.performClearTaskLocked();
1705            mReuseTask = task;
1706            mReuseTask.setIntent(mStartActivity);
1707
1708            // When we clear the task - focus will be adjusted, which will bring another task
1709            // to top before we launch the activity we need. This will temporary swap their
1710            // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1711            mMovedOtherTask = true;
1712        } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1713                || mLaunchSingleInstance || mLaunchSingleTask) {
1714            ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
1715                    mLaunchFlags);
1716            if (top == null) {
1717                // A special case: we need to start the activity because it is not currently
1718                // running, and the caller has asked to clear the current task to have this
1719                // activity at the top.
1720                mAddingToTask = true;
1721
1722                // We are no longer placing the activity in the task we previously thought we were.
1723                mStartActivity.setTask(null);
1724                // Now pretend like this activity is being started by the top of its task, so it
1725                // is put in the right place.
1726                mSourceRecord = intentActivity;
1727                final TaskRecord task = mSourceRecord.getTask();
1728                if (task != null && task.getStack() == null) {
1729                    // Target stack got cleared when we all activities were removed above.
1730                    // Go ahead and reset it.
1731                    mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1732                            null /* bounds */, mLaunchFlags, mOptions);
1733                    mTargetStack.addTask(task,
1734                            !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1735                }
1736            }
1737        } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
1738            // In this case the top activity on the task is the same as the one being launched,
1739            // so we take that as a request to bring the task to the foreground. If the top
1740            // activity in the task is the root activity, deliver this new intent to it if it
1741            // desires.
1742            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1743                    && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1744                if (intentActivity.frontOfTask) {
1745                    intentActivity.getTask().setIntent(mStartActivity);
1746                }
1747                deliverNewIntent(intentActivity);
1748            } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
1749                // In this case we are launching the root activity of the task, but with a
1750                // different intent. We should start a new instance on top.
1751                mAddingToTask = true;
1752                mSourceRecord = intentActivity;
1753            }
1754        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1755            // In this case an activity is being launched in to an existing task, without
1756            // resetting that task. This is typically the situation of launching an activity
1757            // from a notification or shortcut. We want to place the new activity on top of the
1758            // current task.
1759            mAddingToTask = true;
1760            mSourceRecord = intentActivity;
1761        } else if (!intentActivity.getTask().rootWasReset) {
1762            // In this case we are launching into an existing task that has not yet been started
1763            // from its front door. The current task has been brought to the front. Ideally,
1764            // we'd probably like to place this new task at the bottom of its stack, but that's
1765            // a little hard to do with the current organization of the code so for now we'll
1766            // just drop it.
1767            intentActivity.getTask().setIntent(mStartActivity);
1768        }
1769    }
1770
1771    private void resumeTargetStackIfNeeded() {
1772        if (mDoResume) {
1773            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1774        } else {
1775            ActivityOptions.abort(mOptions);
1776        }
1777        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1778    }
1779
1780    private int setTaskFromReuseOrCreateNewTask(
1781            TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1782        mTargetStack = computeStackFocus(
1783                mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1784
1785        // Do no move the target stack to front yet, as we might bail if
1786        // isLockTaskModeViolation fails below.
1787
1788        if (mReuseTask == null) {
1789            final TaskRecord task = mTargetStack.createTaskRecord(
1790                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1791                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1792                    mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1793                    mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
1794            addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
1795            if (mLaunchBounds != null) {
1796                final int stackId = mTargetStack.mStackId;
1797                if (StackId.resizeStackWithLaunchBounds(stackId)) {
1798                    mService.resizeStack(
1799                            stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1800                } else {
1801                    mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
1802                }
1803            }
1804            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1805                    + " in new task " + mStartActivity.getTask());
1806        } else {
1807            addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1808        }
1809
1810        if (taskToAffiliate != null) {
1811            mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
1812        }
1813
1814        if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
1815            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1816            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1817        }
1818
1819        if (!mMovedOtherTask) {
1820            // If stack id is specified in activity options, usually it means that activity is
1821            // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1822            // that case we check the target stack.
1823            updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
1824                    preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1825        }
1826        if (mDoResume) {
1827            mTargetStack.moveToFront("reuseOrNewTask");
1828        }
1829        return START_SUCCESS;
1830    }
1831
1832    private void deliverNewIntent(ActivityRecord activity) {
1833        if (mIntentDelivered) {
1834            return;
1835        }
1836
1837        ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
1838        activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1839                mStartActivity.launchedFromPackage);
1840        mIntentDelivered = true;
1841    }
1842
1843    private int setTaskFromSourceRecord() {
1844        if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
1845            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1846            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1847        }
1848
1849        final TaskRecord sourceTask = mSourceRecord.getTask();
1850        final ActivityStack sourceStack = mSourceRecord.getStack();
1851        // We only want to allow changing stack in two cases:
1852        // 1. If the target task is not the top one. Otherwise we would move the launching task to
1853        //    the other side, rather than show two side by side.
1854        // 2. If activity is not allowed on target display.
1855        final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
1856                : sourceStack.mDisplayId;
1857        final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
1858                || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
1859        if (moveStackAllowed) {
1860            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
1861                    mOptions);
1862            // If target stack is not found now - we can't just rely on the source stack, as it may
1863            // be not suitable. Let's check other displays.
1864            if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
1865                // Can't use target display, lets find a stack on the source display.
1866                mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
1867                        sourceStack.mDisplayId, mStartActivity);
1868            }
1869            if (mTargetStack == null) {
1870                // There are no suitable stacks on the target and source display(s). Look on all
1871                // displays.
1872                mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
1873                        mStartActivity, -1 /* currentFocus */);
1874            }
1875        }
1876
1877        if (mTargetStack == null) {
1878            mTargetStack = sourceStack;
1879        } else if (mTargetStack != sourceStack) {
1880            sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1881                    !ANIMATE, DEFER_RESUME, "launchToSide");
1882        }
1883
1884        final TaskRecord topTask = mTargetStack.topTask();
1885        if (topTask != sourceTask && !mAvoidMoveToFront) {
1886            mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1887                    mStartActivity.appTimeTracker, "sourceTaskToFront");
1888        } else if (mDoResume) {
1889            mTargetStack.moveToFront("sourceStackToFront");
1890        }
1891
1892        if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1893            // In this case, we are adding the activity to an existing task, but the caller has
1894            // asked to clear that task if the activity is already running.
1895            ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1896            mKeepCurTransition = true;
1897            if (top != null) {
1898                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
1899                deliverNewIntent(top);
1900                // For paranoia, make sure we have correctly resumed the top activity.
1901                mTargetStack.mLastPausedActivity = null;
1902                if (mDoResume) {
1903                    mSupervisor.resumeFocusedStackTopActivityLocked();
1904                }
1905                ActivityOptions.abort(mOptions);
1906                return START_DELIVERED_TO_TOP;
1907            }
1908        } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1909            // In this case, we are launching an activity in our own task that may already be
1910            // running somewhere in the history, and we want to shuffle it to the front of the
1911            // stack if so.
1912            final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1913            if (top != null) {
1914                final TaskRecord task = top.getTask();
1915                task.moveActivityToFrontLocked(top);
1916                top.updateOptionsLocked(mOptions);
1917                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1918                deliverNewIntent(top);
1919                mTargetStack.mLastPausedActivity = null;
1920                if (mDoResume) {
1921                    mSupervisor.resumeFocusedStackTopActivityLocked();
1922                }
1923                return START_DELIVERED_TO_TOP;
1924            }
1925        }
1926
1927        // An existing activity is starting this new activity, so we want to keep the new one in
1928        // the same task as the one that is starting it.
1929        addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
1930        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1931                + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
1932        return START_SUCCESS;
1933    }
1934
1935    private int setTaskFromInTask() {
1936        // The caller is asking that the new activity be started in an explicit
1937        // task it has provided to us.
1938        if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1939            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1940            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1941        }
1942
1943        mTargetStack = mInTask.getStack();
1944
1945        // Check whether we should actually launch the new activity in to the task,
1946        // or just reuse the current activity on top.
1947        ActivityRecord top = mInTask.getTopActivity();
1948        if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1949                && top.userId == mStartActivity.userId) {
1950            if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1951                    || mLaunchSingleTop || mLaunchSingleTask) {
1952                mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1953                        mStartActivity.appTimeTracker, "inTaskToFront");
1954                if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1955                    // We don't need to start a new activity, and the client said not to do
1956                    // anything if that is the case, so this is it!
1957                    return START_RETURN_INTENT_TO_CALLER;
1958                }
1959                deliverNewIntent(top);
1960                return START_DELIVERED_TO_TOP;
1961            }
1962        }
1963
1964        if (!mAddingToTask) {
1965            mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1966                    mStartActivity.appTimeTracker, "inTaskToFront");
1967            // We don't actually want to have this activity added to the task, so just
1968            // stop here but still tell the caller that we consumed the intent.
1969            ActivityOptions.abort(mOptions);
1970            return START_TASK_TO_FRONT;
1971        }
1972
1973        if (mLaunchBounds != null) {
1974            mInTask.updateOverrideConfiguration(mLaunchBounds);
1975            int stackId = mInTask.getLaunchStackId();
1976            if (stackId != mInTask.getStackId()) {
1977                mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1978                        DEFER_RESUME, "inTaskToFront");
1979                stackId = mInTask.getStackId();
1980                mTargetStack = mInTask.getStack();
1981            }
1982            if (StackId.resizeStackWithLaunchBounds(stackId)) {
1983                mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1984            }
1985        }
1986
1987        mTargetStack.moveTaskToFrontLocked(
1988                mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1989
1990        addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1991        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1992                + " in explicit task " + mStartActivity.getTask());
1993
1994        return START_SUCCESS;
1995    }
1996
1997    private void setTaskToCurrentTopOrCreateNewTask() {
1998        mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1999                mOptions);
2000        if (mDoResume) {
2001            mTargetStack.moveToFront("addingToTopTask");
2002        }
2003        final ActivityRecord prev = mTargetStack.topActivity();
2004        final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
2005                mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
2006                mIntent, null, null, true, mStartActivity.mActivityType);
2007        addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2008        mTargetStack.positionChildWindowContainerAtTop(task);
2009        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2010                + " in new guessed " + mStartActivity.getTask());
2011    }
2012
2013    private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
2014        if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
2015            parent.addActivityToTop(mStartActivity);
2016        } else {
2017            mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2018        }
2019    }
2020
2021    private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2022            boolean launchSingleTask, int launchFlags) {
2023        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2024                (launchSingleInstance || launchSingleTask)) {
2025            // We have a conflict between the Intent and the Activity manifest, manifest wins.
2026            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2027                    "\"singleInstance\" or \"singleTask\"");
2028            launchFlags &=
2029                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2030        } else {
2031            switch (r.info.documentLaunchMode) {
2032                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2033                    break;
2034                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2035                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2036                    break;
2037                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2038                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2039                    break;
2040                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2041                    launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2042                    break;
2043            }
2044        }
2045        return launchFlags;
2046    }
2047
2048    final void doPendingActivityLaunchesLocked(boolean doResume) {
2049        while (!mPendingActivityLaunches.isEmpty()) {
2050            final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
2051            final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
2052            try {
2053                startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
2054                        null, null /*outRecords*/);
2055            } catch (Exception e) {
2056                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
2057                pal.sendErrorResult(e.getMessage());
2058            }
2059        }
2060    }
2061
2062    private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
2063            int launchFlags, ActivityOptions aOptions) {
2064        final TaskRecord task = r.getTask();
2065        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
2066        if (stack != null) {
2067            return stack;
2068        }
2069
2070        final ActivityStack currentStack = task != null ? task.getStack() : null;
2071        if (currentStack != null) {
2072            if (mSupervisor.mFocusedStack != currentStack) {
2073                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2074                        "computeStackFocus: Setting " + "focused stack to r=" + r
2075                                + " task=" + task);
2076            } else {
2077                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2078                        "computeStackFocus: Focused stack already="
2079                                + mSupervisor.mFocusedStack);
2080            }
2081            return currentStack;
2082        }
2083
2084        if (canLaunchIntoFocusedStack(r, newTask)) {
2085            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2086                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2087            return mSupervisor.mFocusedStack;
2088        }
2089
2090        if (mSourceDisplayId != DEFAULT_DISPLAY) {
2091            // Try to put the activity in a stack on a secondary display.
2092            stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2093            if (stack == null) {
2094                // If source display is not suitable - look for topmost valid stack in the system.
2095                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2096                        "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
2097                                + ", looking on all displays.");
2098                stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
2099            }
2100        }
2101        if (stack == null) {
2102            // We first try to put the task in the first dynamic stack on home display.
2103            final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2104            for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2105                stack = homeDisplayStacks.get(stackNdx);
2106                if (isDynamicStack(stack.mStackId)) {
2107                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2108                            "computeStackFocus: Setting focused stack=" + stack);
2109                    return stack;
2110                }
2111            }
2112            // If there is no suitable dynamic stack then we figure out which static stack to use.
2113            final int stackId = task != null ? task.getLaunchStackId() :
2114                    bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2115                            FULLSCREEN_WORKSPACE_STACK_ID;
2116            stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
2117        }
2118        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2119                + r + " stackId=" + stack.mStackId);
2120        return stack;
2121    }
2122
2123    /** Check if provided activity record can launch in currently focused stack. */
2124    private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
2125        final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2126        final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2127        final boolean canUseFocusedStack;
2128        switch (focusedStackId) {
2129            case FULLSCREEN_WORKSPACE_STACK_ID:
2130                // The fullscreen stack can contain any task regardless of if the task is resizeable
2131                // or not. So, we let the task go in the fullscreen task if it is the focus stack.
2132                canUseFocusedStack = true;
2133                break;
2134            case ASSISTANT_STACK_ID:
2135                canUseFocusedStack = r.isAssistantActivity();
2136                break;
2137            case DOCKED_STACK_ID:
2138                // Any activity which supports split screen can go in the docked stack.
2139                canUseFocusedStack = r.supportsSplitScreen();
2140                break;
2141            case FREEFORM_WORKSPACE_STACK_ID:
2142                // Any activity which supports freeform can go in the freeform stack.
2143                canUseFocusedStack = r.supportsFreeform();
2144                break;
2145            default:
2146                // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2147                // resizeable task.
2148                canUseFocusedStack = isDynamicStack(focusedStackId)
2149                        && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2150        }
2151
2152        return canUseFocusedStack && !newTask
2153                // We strongly prefer to launch activities on the same display as their source.
2154                && (mSourceDisplayId == focusedStack.mDisplayId);
2155    }
2156
2157    private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
2158            ActivityOptions aOptions) {
2159        // We are reusing a task, keep the stack!
2160        if (mReuseTask != null) {
2161            return mReuseTask.getStack();
2162        }
2163
2164        // If the activity is of a specific type, return the associated stack, creating it if
2165        // necessary
2166        if (r.isHomeActivity()) {
2167            return mSupervisor.mHomeStack;
2168        }
2169        if (r.isRecentsActivity()) {
2170            return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2171        }
2172        if (r.isAssistantActivity()) {
2173            return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2174        }
2175
2176        final int launchDisplayId =
2177                (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2178
2179        final int launchStackId =
2180                (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2181
2182        if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2183            throw new IllegalArgumentException(
2184                    "Stack and display id can't be set at the same time.");
2185        }
2186
2187        if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
2188            return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
2189        }
2190        if (launchStackId == DOCKED_STACK_ID) {
2191            // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2192            // for this activity, so we put the activity in the fullscreen stack.
2193            return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2194        }
2195        if (launchDisplayId != INVALID_DISPLAY) {
2196            // Stack id has higher priority than display id.
2197            return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2198        }
2199
2200        // If we are using Vr2d display, find the virtual display stack.
2201        if (mUsingVr2dDisplay) {
2202            ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2203            if (DEBUG_STACK) {
2204                Slog.v(TAG, "Launch stack for app: " + r.toString() +
2205                    ", on virtual display stack:" + as.toString());
2206            }
2207            return as;
2208        }
2209
2210        if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2211                 || mSourceDisplayId != DEFAULT_DISPLAY) {
2212            return null;
2213        }
2214        // Otherwise handle adjacent launch.
2215
2216        // The parent activity doesn't want to launch the activity on top of itself, but
2217        // instead tries to put it onto other side in side-by-side mode.
2218        final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
2219
2220        if (parentStack != mSupervisor.mFocusedStack) {
2221            // If task's parent stack is not focused - use it during adjacent launch.
2222            return parentStack;
2223        } else {
2224            if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2225                // If task is already on top of focused stack - use it. We don't want to move the
2226                // existing focused task to adjacent stack, just deliver new intent in this case.
2227                return mSupervisor.mFocusedStack;
2228            }
2229
2230            if (parentStack != null && parentStack.isDockedStack()) {
2231                // If parent was in docked stack, the natural place to launch another activity
2232                // will be fullscreen, so it can appear alongside the docked window.
2233                return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2234                        ON_TOP);
2235            } else {
2236                // If the parent is not in the docked stack, we check if there is docked window
2237                // and if yes, we will launch into that stack. If not, we just put the new
2238                // activity into parent's stack, because we can't find a better place.
2239                final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2240                if (dockedStack != null
2241                        && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
2242                    // There is a docked stack, but it isn't visible, so we can't launch into that.
2243                    return null;
2244                } else {
2245                    return dockedStack;
2246                }
2247            }
2248        }
2249    }
2250
2251    boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
2252        switch (stackId) {
2253            case INVALID_STACK_ID:
2254            case HOME_STACK_ID:
2255                return false;
2256            case FULLSCREEN_WORKSPACE_STACK_ID:
2257                return true;
2258            case FREEFORM_WORKSPACE_STACK_ID:
2259                return r.supportsFreeform();
2260            case DOCKED_STACK_ID:
2261                return r.supportsSplitScreen();
2262            case PINNED_STACK_ID:
2263                return r.supportsPictureInPicture();
2264            case RECENTS_STACK_ID:
2265                return r.isRecentsActivity();
2266            case ASSISTANT_STACK_ID:
2267                return r.isAssistantActivity();
2268            default:
2269                if (StackId.isDynamicStack(stackId)) {
2270                    return r.canBeLaunchedOnDisplay(displayId);
2271                }
2272                Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2273                return false;
2274        }
2275    }
2276
2277    Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2278        Rect newBounds = null;
2279        if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2280            if (mSupervisor.canUseActivityOptionsLaunchBounds(
2281                    options, options.getLaunchStackId())) {
2282                newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2283            }
2284        }
2285        return newBounds;
2286    }
2287
2288    void setWindowManager(WindowManagerService wm) {
2289        mWindowManager = wm;
2290    }
2291
2292    void removePendingActivityLaunchesLocked(ActivityStack stack) {
2293        for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2294            PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2295            if (pal.stack == stack) {
2296                mPendingActivityLaunches.remove(palNdx);
2297            }
2298        }
2299    }
2300
2301    static boolean isDocumentLaunchesIntoExisting(int flags) {
2302        return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2303                (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2304    }
2305
2306    boolean clearPendingActivityLaunchesLocked(String packageName) {
2307        boolean didSomething = false;
2308
2309        for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2310            PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2311            ActivityRecord r = pal.r;
2312            if (r != null && r.packageName.equals(packageName)) {
2313                mPendingActivityLaunches.remove(palNdx);
2314                didSomething = true;
2315            }
2316        }
2317        return didSomething;
2318    }
2319
2320    void dump(PrintWriter pw, String prefix, String dumpPackage) {
2321        prefix = prefix + "  ";
2322
2323        if (dumpPackage != null) {
2324            if ((mLastStartActivityRecord[0] == null ||
2325                    !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2326                    (mLastHomeActivityStartRecord[0] == null ||
2327                    !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2328                    (mStartActivity == null || !dumpPackage.equals(mStartActivity.packageName))) {
2329                pw.print(prefix);
2330                pw.println("(nothing)");
2331                return;
2332            }
2333        }
2334
2335        pw.print(prefix);
2336        pw.print("mCurrentUser=");
2337        pw.println(mSupervisor.mCurrentUser);
2338        pw.print(prefix);
2339        pw.print("mLastStartReason=");
2340        pw.println(mLastStartReason);
2341        pw.print(prefix);
2342        pw.print("mLastStartActivityTimeMs=");
2343        pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2344        pw.print(prefix);
2345        pw.print("mLastStartActivityResult=");
2346        pw.println(mLastStartActivityResult);
2347        ActivityRecord r = mLastStartActivityRecord[0];
2348        if (r != null) {
2349            pw.print(prefix);
2350            pw.println("mLastStartActivityRecord:");
2351            r.dump(pw, prefix + "  ");
2352        }
2353        pw.print(prefix);
2354        pw.print("mLastHomeActivityStartResult=");
2355        pw.println(mLastHomeActivityStartResult);
2356        r = mLastHomeActivityStartRecord[0];
2357        if (r != null) {
2358            pw.print(prefix);
2359            pw.println("mLastHomeActivityStartRecord:");
2360            r.dump(pw, prefix + "  ");
2361        }
2362        if (mStartActivity != null) {
2363            pw.print(prefix);
2364            pw.println("mStartActivity:");
2365            mStartActivity.dump(pw, prefix + "  ");
2366        }
2367        if (mIntent != null) {
2368            pw.print(prefix);
2369            pw.print("mIntent=");
2370            pw.println(mIntent);
2371        }
2372        if (mOptions != null) {
2373            pw.print(prefix);
2374            pw.print("mOptions=");
2375            pw.println(mOptions);
2376        }
2377        pw.print(prefix);
2378        pw.print("mLaunchSingleTop=");
2379        pw.print(mLaunchSingleTop);
2380        pw.print(" mLaunchSingleInstance=");
2381        pw.print(mLaunchSingleInstance);
2382        pw.print(" mLaunchSingleTask=");
2383        pw.println(mLaunchSingleTask);
2384        pw.print(prefix);
2385        pw.print("mLaunchFlags=0x");
2386        pw.print(Integer.toHexString(mLaunchFlags));
2387        pw.print(" mDoResume=");
2388        pw.print(mDoResume);
2389        pw.print(" mAddingToTask=");
2390        pw.println(mAddingToTask);
2391    }
2392}
2393