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