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