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