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