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