ActivityStarter.java revision c8cccdcbd3ea8511b17d58ddbdc4a15e440f7f89
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            // TODO; do we need any extras for the installer?
548            ephemeralIntent = new Intent(launchIntent);
549            ephemeralIntent.setData(null);
550        }
551
552        // Intent that is eventually launched if the ephemeral package was
553        // installed successfully. This will actually be launched by a platform
554        // broadcast receiver.
555        final IIntentSender successIntentTarget = mService.getIntentSenderLocked(
556                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
557                Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0,
558                new Intent[]{ ephemeralIntent }, new String[]{ resolvedType },
559                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
560                | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
561
562        // Finally build the actual intent to launch the ephemeral installer
563        int flags = launchIntent.getFlags();
564        final Intent intent = new Intent();
565        intent.setFlags(flags
566                | Intent.FLAG_ACTIVITY_NEW_TASK
567                | Intent.FLAG_ACTIVITY_CLEAR_TASK
568                | Intent.FLAG_ACTIVITY_NO_HISTORY
569                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
570        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
571        intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
572        intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
573        // TODO: Remove when the platform has fully implemented ephemeral apps
574        intent.setData(origIntent.getData());
575        return intent;
576    }
577
578    void postStartActivityUncheckedProcessing(
579            ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
580            ActivityStack targetStack) {
581
582        if (result < START_SUCCESS) {
583            // If someone asked to have the keyguard dismissed on the next activity start,
584            // but we are not actually doing an activity switch...  just dismiss the keyguard now,
585            // because we probably want to see whatever is behind it.
586            mSupervisor.notifyActivityDrawnForKeyguard();
587            return;
588        }
589
590        // We're waiting for an activity launch to finish, but that activity simply
591        // brought another activity to front. Let startActivityMayWait() know about
592        // this, so it waits for the new activity to become visible instead.
593        if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
594            mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
595        }
596
597        int startedActivityStackId = INVALID_STACK_ID;
598        if (r.task != null && r.task.stack != null) {
599            startedActivityStackId = r.task.stack.mStackId;
600        } else if (mTargetStack != null) {
601            startedActivityStackId = targetStack.mStackId;
602        }
603
604        // If we launched the activity from a no display activity that was launched from the home
605        // screen, we also need to start recents to un-minimize the docked stack, since the
606        // noDisplay activity will be finished shortly after.
607        // Note that some apps have trampoline activities without noDisplay being set. In that case,
608        // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
609        // that tries to detect that case.
610        // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
611        // visibility instead of using this flag.
612        final boolean noDisplayActivityOverHome = sourceRecord != null
613                && sourceRecord.noDisplay
614                && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
615        if (startedActivityStackId == DOCKED_STACK_ID
616                && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
617            final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
618            final ActivityRecord topActivityHomeStack = homeStack != null
619                    ? homeStack.topRunningActivityLocked() : null;
620            if (topActivityHomeStack == null
621                    || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
622                // We launch an activity while being in home stack, which means either launcher or
623                // recents into docked stack. We don't want the launched activity to be alone in a
624                // docked stack, so we want to immediately launch recents too.
625                if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
626                mWindowManager.showRecentApps(true /* fromHome */);
627                return;
628            }
629        }
630
631        if (startedActivityStackId == PINNED_STACK_ID
632                && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
633            // The activity was already running in the pinned stack so it wasn't started, but either
634            // brought to the front or the new intent was delivered to it since it was already in
635            // front. Notify anyone interested in this piece of information.
636            mService.notifyPinnedActivityRestartAttemptLocked();
637            return;
638        }
639    }
640
641    void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
642        mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
643        startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
644                null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
645                null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
646                0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
647                0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
648                false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
649                null /*container*/, null /*inTask*/);
650        if (mSupervisor.inResumeTopActivity) {
651            // If we are in resume section already, home activity will be initialized, but not
652            // resumed (to avoid recursive resume) and will stay that way until something pokes it
653            // again. We need to schedule another resume.
654            mSupervisor.scheduleResumeTopActivities();
655        }
656    }
657
658    void showConfirmDeviceCredential(int userId) {
659        // First, retrieve the stack that we want to resume after credential is confirmed.
660        ActivityStack targetStack;
661        ActivityStack fullscreenStack =
662                mSupervisor.getStack(FULLSCREEN_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 {
668            // The case that the docked stack is shown with recent.
669            targetStack = mSupervisor.getStack(HOME_STACK_ID);
670        }
671        if (targetStack == null) {
672            return;
673        }
674        final KeyguardManager km = (KeyguardManager) mService.mContext
675                .getSystemService(Context.KEYGUARD_SERVICE);
676        final Intent credential =
677                km.createConfirmDeviceCredentialIntent(null, null, userId);
678        // For safety, check null here in case users changed the setting after the checking.
679        if (credential == null) {
680            return;
681        }
682        final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
683        if (activityRecord != null) {
684            final IIntentSender target = mService.getIntentSenderLocked(
685                    ActivityManager.INTENT_SENDER_ACTIVITY,
686                    activityRecord.launchedFromPackage,
687                    activityRecord.launchedFromUid,
688                    activityRecord.userId,
689                    null, null, 0,
690                    new Intent[] { activityRecord.intent },
691                    new String[] { activityRecord.resolvedType },
692                    PendingIntent.FLAG_CANCEL_CURRENT |
693                            PendingIntent.FLAG_ONE_SHOT |
694                            PendingIntent.FLAG_IMMUTABLE,
695                    null);
696            credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
697            // Show confirm credentials activity.
698            startConfirmCredentialIntent(credential);
699        }
700    }
701
702    void startConfirmCredentialIntent(Intent intent) {
703        intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
704                FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
705                FLAG_ACTIVITY_TASK_ON_HOME);
706        final ActivityOptions options = ActivityOptions.makeBasic();
707        options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
708        mService.mContext.startActivityAsUser(intent, options.toBundle(),
709                UserHandle.CURRENT);
710    }
711
712    final int startActivityMayWait(IApplicationThread caller, int callingUid,
713            String callingPackage, Intent intent, String resolvedType,
714            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
715            IBinder resultTo, String resultWho, int requestCode, int startFlags,
716            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
717            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
718            IActivityContainer iContainer, TaskRecord inTask) {
719        // Refuse possible leaked file descriptors
720        if (intent != null && intent.hasFileDescriptors()) {
721            throw new IllegalArgumentException("File descriptors passed in Intent");
722        }
723        mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
724        boolean componentSpecified = intent.getComponent() != null;
725
726        // Save a copy in case ephemeral needs it
727        final Intent ephemeralIntent = new Intent(intent);
728        // Don't modify the client's object!
729        intent = new Intent(intent);
730
731        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
732        if (rInfo == null) {
733            UserInfo userInfo = mSupervisor.getUserInfo(userId);
734            if (userInfo != null && userInfo.isManagedProfile()) {
735                // Special case for managed profiles, if attempting to launch non-cryto aware
736                // app in a locked managed profile from an unlocked parent allow it to resolve
737                // as user will be sent via confirm credentials to unlock the profile.
738                UserManager userManager = UserManager.get(mService.mContext);
739                boolean profileLockedAndParentUnlockingOrUnlocked = false;
740                long token = Binder.clearCallingIdentity();
741                try {
742                    UserInfo parent = userManager.getProfileParent(userId);
743                    profileLockedAndParentUnlockingOrUnlocked = (parent != null)
744                            && userManager.isUserUnlockingOrUnlocked(parent.id)
745                            && !userManager.isUserUnlockingOrUnlocked(userId);
746                } finally {
747                    Binder.restoreCallingIdentity(token);
748                }
749                if (profileLockedAndParentUnlockingOrUnlocked) {
750                    rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
751                            PackageManager.MATCH_DIRECT_BOOT_AWARE
752                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
753                }
754            }
755        }
756        // Collect information about the target of the Intent.
757        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
758
759        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
760        ActivityStackSupervisor.ActivityContainer container =
761                (ActivityStackSupervisor.ActivityContainer)iContainer;
762        synchronized (mService) {
763            if (container != null && container.mParentActivity != null &&
764                    container.mParentActivity.state != RESUMED) {
765                // Cannot start a child activity if the parent is not resumed.
766                return ActivityManager.START_CANCELED;
767            }
768            final int realCallingPid = Binder.getCallingPid();
769            final int realCallingUid = Binder.getCallingUid();
770            int callingPid;
771            if (callingUid >= 0) {
772                callingPid = -1;
773            } else if (caller == null) {
774                callingPid = realCallingPid;
775                callingUid = realCallingUid;
776            } else {
777                callingPid = callingUid = -1;
778            }
779
780            final ActivityStack stack;
781            if (container == null || container.mStack.isOnHomeDisplay()) {
782                stack = mSupervisor.mFocusedStack;
783            } else {
784                stack = container.mStack;
785            }
786            stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
787            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
788                    "Starting activity when config will change = " + stack.mConfigWillChange);
789
790            final long origId = Binder.clearCallingIdentity();
791
792            if (aInfo != null &&
793                    (aInfo.applicationInfo.privateFlags
794                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
795                // This may be a heavy-weight process!  Check to see if we already
796                // have another, different heavy-weight process running.
797                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
798                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
799                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
800                            || !heavy.processName.equals(aInfo.processName))) {
801                        int appCallingUid = callingUid;
802                        if (caller != null) {
803                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
804                            if (callerApp != null) {
805                                appCallingUid = callerApp.info.uid;
806                            } else {
807                                Slog.w(TAG, "Unable to find app for caller " + caller
808                                        + " (pid=" + callingPid + ") when starting: "
809                                        + intent.toString());
810                                ActivityOptions.abort(options);
811                                return ActivityManager.START_PERMISSION_DENIED;
812                            }
813                        }
814
815                        IIntentSender target = mService.getIntentSenderLocked(
816                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
817                                appCallingUid, userId, null, null, 0, new Intent[] { intent },
818                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
819                                        | PendingIntent.FLAG_ONE_SHOT, null);
820
821                        Intent newIntent = new Intent();
822                        if (requestCode >= 0) {
823                            // Caller is requesting a result.
824                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
825                        }
826                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
827                                new IntentSender(target));
828                        if (heavy.activities.size() > 0) {
829                            ActivityRecord hist = heavy.activities.get(0);
830                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
831                                    hist.packageName);
832                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
833                                    hist.task.taskId);
834                        }
835                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
836                                aInfo.packageName);
837                        newIntent.setFlags(intent.getFlags());
838                        newIntent.setClassName("android",
839                                HeavyWeightSwitcherActivity.class.getName());
840                        intent = newIntent;
841                        resolvedType = null;
842                        caller = null;
843                        callingUid = Binder.getCallingUid();
844                        callingPid = Binder.getCallingPid();
845                        componentSpecified = true;
846                        rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
847                        aInfo = rInfo != null ? rInfo.activityInfo : null;
848                        if (aInfo != null) {
849                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
850                        }
851                    }
852                }
853            }
854
855            final ActivityRecord[] outRecord = new ActivityRecord[1];
856            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
857                    aInfo, rInfo, voiceSession, voiceInteractor,
858                    resultTo, resultWho, requestCode, callingPid,
859                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
860                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
861                    inTask);
862
863            Binder.restoreCallingIdentity(origId);
864
865            if (stack.mConfigWillChange) {
866                // If the caller also wants to switch to a new configuration,
867                // do so now.  This allows a clean switch, as we are waiting
868                // for the current activity to pause (so we will not destroy
869                // it), and have not yet started the next activity.
870                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
871                        "updateConfiguration()");
872                stack.mConfigWillChange = false;
873                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
874                        "Updating to new configuration after starting activity.");
875                mService.updateConfigurationLocked(config, null, false);
876            }
877
878            if (outResult != null) {
879                outResult.result = res;
880                if (res == ActivityManager.START_SUCCESS) {
881                    mSupervisor.mWaitingActivityLaunched.add(outResult);
882                    do {
883                        try {
884                            mService.wait();
885                        } catch (InterruptedException e) {
886                        }
887                    } while (outResult.result != START_TASK_TO_FRONT
888                            && !outResult.timeout && outResult.who == null);
889                    if (outResult.result == START_TASK_TO_FRONT) {
890                        res = START_TASK_TO_FRONT;
891                    }
892                }
893                if (res == START_TASK_TO_FRONT) {
894                    ActivityRecord r = stack.topRunningActivityLocked();
895                    if (r.nowVisible && r.state == RESUMED) {
896                        outResult.timeout = false;
897                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
898                        outResult.totalTime = 0;
899                        outResult.thisTime = 0;
900                    } else {
901                        outResult.thisTime = SystemClock.uptimeMillis();
902                        mSupervisor.mWaitingActivityVisible.add(outResult);
903                        do {
904                            try {
905                                mService.wait();
906                            } catch (InterruptedException e) {
907                            }
908                        } while (!outResult.timeout && outResult.who == null);
909                    }
910                }
911            }
912
913            final ActivityRecord launchedActivity = mReusedActivity != null
914                    ? mReusedActivity : outRecord[0];
915            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
916            return res;
917        }
918    }
919
920    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
921            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
922            Bundle bOptions, int userId) {
923        if (intents == null) {
924            throw new NullPointerException("intents is null");
925        }
926        if (resolvedTypes == null) {
927            throw new NullPointerException("resolvedTypes is null");
928        }
929        if (intents.length != resolvedTypes.length) {
930            throw new IllegalArgumentException("intents are length different than resolvedTypes");
931        }
932
933        final int realCallingPid = Binder.getCallingPid();
934        final int realCallingUid = Binder.getCallingUid();
935
936        int callingPid;
937        if (callingUid >= 0) {
938            callingPid = -1;
939        } else if (caller == null) {
940            callingPid = realCallingPid;
941            callingUid = realCallingUid;
942        } else {
943            callingPid = callingUid = -1;
944        }
945        final long origId = Binder.clearCallingIdentity();
946        try {
947            synchronized (mService) {
948                ActivityRecord[] outActivity = new ActivityRecord[1];
949                for (int i=0; i<intents.length; i++) {
950                    Intent intent = intents[i];
951                    if (intent == null) {
952                        continue;
953                    }
954
955                    // Refuse possible leaked file descriptors
956                    if (intent != null && intent.hasFileDescriptors()) {
957                        throw new IllegalArgumentException("File descriptors passed in Intent");
958                    }
959
960                    boolean componentSpecified = intent.getComponent() != null;
961
962                    // Don't modify the client's object!
963                    intent = new Intent(intent);
964
965                    // Collect information about the target of the Intent.
966                    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
967                            null, userId);
968                    // TODO: New, check if this is correct
969                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
970
971                    if (aInfo != null &&
972                            (aInfo.applicationInfo.privateFlags
973                                    & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
974                        throw new IllegalArgumentException(
975                                "FLAG_CANT_SAVE_STATE not supported here");
976                    }
977
978                    ActivityOptions options = ActivityOptions.fromBundle(
979                            i == intents.length - 1 ? bOptions : null);
980                    int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
981                            resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
982                            callingPid, callingUid, callingPackage,
983                            realCallingPid, realCallingUid, 0,
984                            options, false, componentSpecified, outActivity, null, null);
985                    if (res < 0) {
986                        return res;
987                    }
988
989                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
990                }
991            }
992        } finally {
993            Binder.restoreCallingIdentity(origId);
994        }
995
996        return START_SUCCESS;
997    }
998
999    void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
1000        // Trigger launch power hint if activity being launched is not in the current task
1001        final ActivityStack focusStack = mSupervisor.getFocusedStack();
1002        final ActivityRecord curTop = (focusStack == null)
1003            ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1004        if ((forceSend || (!mPowerHintSent && curTop != null &&
1005                curTop.task != null && mStartActivity != null &&
1006                curTop.task != mStartActivity.task )) &&
1007                mService.mLocalPowerManager != null) {
1008            mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
1009            mPowerHintSent = true;
1010        }
1011    }
1012
1013    void sendPowerHintForLaunchEndIfNeeded() {
1014        // Trigger launch power hint if activity is launched
1015        if (mPowerHintSent && mService.mLocalPowerManager != null) {
1016            mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
1017            mPowerHintSent = false;
1018        }
1019    }
1020
1021    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1022            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1023            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1024
1025        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1026                voiceInteractor);
1027
1028        computeLaunchingTaskFlags();
1029
1030        computeSourceStack();
1031
1032        mIntent.setFlags(mLaunchFlags);
1033
1034        mReusedActivity = getReusableIntentActivity();
1035
1036        final int preferredLaunchStackId =
1037                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1038
1039        if (mReusedActivity != null) {
1040            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1041            // still needs to be a lock task mode violation since the task gets cleared out and
1042            // the device would otherwise leave the locked task.
1043            if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
1044                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1045                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1046                mSupervisor.showLockTaskToast();
1047                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1048                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1049            }
1050
1051            if (mStartActivity.task == null) {
1052                mStartActivity.task = mReusedActivity.task;
1053            }
1054            if (mReusedActivity.task.intent == null) {
1055                // This task was started because of movement of the activity based on affinity...
1056                // Now that we are actually launching it, we can assign the base intent.
1057                mReusedActivity.task.setIntent(mStartActivity);
1058            }
1059
1060            // This code path leads to delivering a new intent, we want to make sure we schedule it
1061            // as the first operation, in case the activity will be resumed as a result of later
1062            // operations.
1063            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1064                    || mLaunchSingleInstance || mLaunchSingleTask) {
1065                // In this situation we want to remove all activities from the task up to the one
1066                // being started. In most cases this means we are resetting the task to its initial
1067                // state.
1068                final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
1069                        mStartActivity, mLaunchFlags);
1070                if (top != null) {
1071                    if (top.frontOfTask) {
1072                        // Activity aliases may mean we use different intents for the top activity,
1073                        // so make sure the task now has the identity of the new intent.
1074                        top.task.setIntent(mStartActivity);
1075                    }
1076                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1077                    top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1078                            mStartActivity.launchedFromPackage);
1079                }
1080            }
1081
1082            sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1083
1084            mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
1085
1086            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1087                // We don't need to start a new activity, and the client said not to do anything
1088                // if that is the case, so this is it!  And for paranoia, make sure we have
1089                // correctly resumed the top activity.
1090                resumeTargetStackIfNeeded();
1091                return START_RETURN_INTENT_TO_CALLER;
1092            }
1093            setTaskFromIntentActivity(mReusedActivity);
1094
1095            if (!mAddingToTask && mReuseTask == null) {
1096                // We didn't do anything...  but it was needed (a.k.a., client don't use that
1097                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
1098                resumeTargetStackIfNeeded();
1099                return START_TASK_TO_FRONT;
1100            }
1101        }
1102
1103        if (mStartActivity.packageName == null) {
1104            if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1105                mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1106                        -1, mStartActivity.resultTo, mStartActivity.resultWho,
1107                        mStartActivity.requestCode, RESULT_CANCELED, null);
1108            }
1109            ActivityOptions.abort(mOptions);
1110            return START_CLASS_NOT_FOUND;
1111        }
1112
1113        // If the activity being launched is the same as the one currently at the top, then
1114        // we need to check if it should only be launched once.
1115        final ActivityStack topStack = mSupervisor.mFocusedStack;
1116        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1117        final boolean dontStart = top != null && mStartActivity.resultTo == null
1118                && top.realActivity.equals(mStartActivity.realActivity)
1119                && top.userId == mStartActivity.userId
1120                && top.app != null && top.app.thread != null
1121                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1122                || mLaunchSingleTop || mLaunchSingleTask);
1123        if (dontStart) {
1124            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1125            // For paranoia, make sure we have correctly resumed the top activity.
1126            topStack.mLastPausedActivity = null;
1127            if (mDoResume) {
1128                mSupervisor.resumeFocusedStackTopActivityLocked();
1129            }
1130            ActivityOptions.abort(mOptions);
1131            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1132                // We don't need to start a new activity, and the client said not to do
1133                // anything if that is the case, so this is it!
1134                return START_RETURN_INTENT_TO_CALLER;
1135            }
1136            top.deliverNewIntentLocked(
1137                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1138
1139            // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1140            // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1141            mSupervisor.handleNonResizableTaskIfNeeded(
1142                    top.task, preferredLaunchStackId, topStack.mStackId);
1143
1144            return START_DELIVERED_TO_TOP;
1145        }
1146
1147        boolean newTask = false;
1148        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1149                ? mSourceRecord.task : null;
1150
1151        // Should this be considered a new task?
1152        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1153                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1154            newTask = true;
1155            setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1156
1157            if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1158                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1159                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1160            }
1161            if (!mMovedOtherTask) {
1162                // If stack id is specified in activity options, usually it means that activity is
1163                // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1164                // that case we check the target stack.
1165                updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1166                        preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1167            }
1168        } else if (mSourceRecord != null) {
1169            if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1170                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1171                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1172            }
1173
1174            final int result = setTaskFromSourceRecord();
1175            if (result != START_SUCCESS) {
1176                return result;
1177            }
1178        } else if (mInTask != null) {
1179            // The caller is asking that the new activity be started in an explicit
1180            // task it has provided to us.
1181            if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1182                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1183                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1184            }
1185
1186            final int result = setTaskFromInTask();
1187            if (result != START_SUCCESS) {
1188                return result;
1189            }
1190        } else {
1191            // This not being started from an existing activity, and not part of a new task...
1192            // just put it in the top task, though these days this case should never happen.
1193            setTaskToCurrentTopOrCreateNewTask();
1194        }
1195
1196        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1197                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1198
1199        if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1200            mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1201        }
1202        if (newTask) {
1203            EventLog.writeEvent(
1204                    EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1205        }
1206        ActivityStack.logStartActivity(
1207                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1208        mTargetStack.mLastPausedActivity = null;
1209
1210        sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1211
1212        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1213        if (mDoResume) {
1214            if (!mLaunchTaskBehind) {
1215                // TODO(b/26381750): Remove this code after verification that all the decision
1216                // points above moved targetStack to the front which will also set the focus
1217                // activity.
1218                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1219            }
1220            final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1221            if (!mTargetStack.isFocusable()
1222                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1223                    && mStartActivity != topTaskActivity)) {
1224                // If the activity is not focusable, we can't resume it, but still would like to
1225                // make sure it becomes visible as it starts (this will also trigger entry
1226                // animation). An example of this are PIP activities.
1227                // Also, we don't want to resume activities in a task that currently has an overlay
1228                // as the starting activity just needs to be in the visible paused state until the
1229                // over is removed.
1230                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1231                // Go ahead and tell window manager to execute app transition for this activity
1232                // since the app transition will not be triggered through the resume channel.
1233                mWindowManager.executeAppTransition();
1234            } else {
1235                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1236                        mOptions);
1237            }
1238        } else {
1239            mTargetStack.addRecentActivityLocked(mStartActivity);
1240        }
1241        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1242
1243        mSupervisor.handleNonResizableTaskIfNeeded(
1244                mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
1245
1246        return START_SUCCESS;
1247    }
1248
1249    private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1250            boolean doResume, int startFlags, ActivityRecord sourceRecord,
1251            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1252        reset();
1253
1254        mStartActivity = r;
1255        mIntent = r.intent;
1256        mOptions = options;
1257        mCallingUid = r.launchedFromUid;
1258        mSourceRecord = sourceRecord;
1259        mVoiceSession = voiceSession;
1260        mVoiceInteractor = voiceInteractor;
1261
1262        mLaunchBounds = getOverrideBounds(r, options, inTask);
1263
1264        mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1265        mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1266        mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1267        mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1268                r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1269        mLaunchTaskBehind = r.mLaunchTaskBehind
1270                && !mLaunchSingleTask && !mLaunchSingleInstance
1271                && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1272
1273        sendNewTaskResultRequestIfNeeded();
1274
1275        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1276            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1277        }
1278
1279        // If we are actually going to launch in to a new task, there are some cases where
1280        // we further want to do multiple task.
1281        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1282            if (mLaunchTaskBehind
1283                    || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1284                mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1285            }
1286        }
1287
1288        // We'll invoke onUserLeaving before onPause only if the launching
1289        // activity did not explicitly state that this is an automated launch.
1290        mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1291        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1292                "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1293
1294        // If the caller has asked not to resume at this point, we make note
1295        // of this in the record so that we can skip it when trying to find
1296        // the top running activity.
1297        mDoResume = doResume;
1298        if (!doResume || !mSupervisor.okToShowLocked(r)) {
1299            r.delayedResume = true;
1300            mDoResume = false;
1301        }
1302
1303        if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1304            r.mTaskOverlay = true;
1305            final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1306            final ActivityRecord top = task != null ? task.getTopActivity() : null;
1307            if (top != null && !top.visible) {
1308
1309                // The caller specifies that we'd like to be avoided to be moved to the front, so be
1310                // it!
1311                mDoResume = false;
1312                mAvoidMoveToFront = true;
1313            }
1314        }
1315
1316        mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1317
1318        mInTask = inTask;
1319        // In some flows in to this function, we retrieve the task record and hold on to it
1320        // without a lock before calling back in to here...  so the task at this point may
1321        // not actually be in recents.  Check for that, and if it isn't in recents just
1322        // consider it invalid.
1323        if (inTask != null && !inTask.inRecents) {
1324            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1325            mInTask = null;
1326        }
1327
1328        mStartFlags = startFlags;
1329        // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1330        // is the same as the one making the call...  or, as a special case, if we do not know
1331        // the caller then we count the current top activity as the caller.
1332        if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1333            ActivityRecord checkedCaller = sourceRecord;
1334            if (checkedCaller == null) {
1335                checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1336                        mNotTop);
1337            }
1338            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1339                // Caller is not the same as launcher, so always needed.
1340                mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1341            }
1342        }
1343
1344        mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1345    }
1346
1347    private void sendNewTaskResultRequestIfNeeded() {
1348        if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1349                && mStartActivity.resultTo.task.stack != null) {
1350            // For whatever reason this activity is being launched into a new task...
1351            // yet the caller has requested a result back.  Well, that is pretty messed up,
1352            // so instead immediately send back a cancel and let the new task continue launched
1353            // as normal without a dependency on its originator.
1354            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1355            mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1356                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1357            mStartActivity.resultTo = null;
1358        }
1359    }
1360
1361    private void computeLaunchingTaskFlags() {
1362        // If the caller is not coming from another activity, but has given us an explicit task into
1363        // which they would like us to launch the new activity, then let's see about doing that.
1364        if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1365            final Intent baseIntent = mInTask.getBaseIntent();
1366            final ActivityRecord root = mInTask.getRootActivity();
1367            if (baseIntent == null) {
1368                ActivityOptions.abort(mOptions);
1369                throw new IllegalArgumentException("Launching into task without base intent: "
1370                        + mInTask);
1371            }
1372
1373            // If this task is empty, then we are adding the first activity -- it
1374            // determines the root, and must be launching as a NEW_TASK.
1375            if (mLaunchSingleInstance || mLaunchSingleTask) {
1376                if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1377                    ActivityOptions.abort(mOptions);
1378                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1379                            + mStartActivity + " into different task " + mInTask);
1380                }
1381                if (root != null) {
1382                    ActivityOptions.abort(mOptions);
1383                    throw new IllegalArgumentException("Caller with mInTask " + mInTask
1384                            + " has root " + root + " but target is singleInstance/Task");
1385                }
1386            }
1387
1388            // If task is empty, then adopt the interesting intent launch flags in to the
1389            // activity being started.
1390            if (root == null) {
1391                final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1392                        | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1393                mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1394                        | (baseIntent.getFlags() & flagsOfInterest);
1395                mIntent.setFlags(mLaunchFlags);
1396                mInTask.setIntent(mStartActivity);
1397                mAddingToTask = true;
1398
1399                // If the task is not empty and the caller is asking to start it as the root of
1400                // a new task, then we don't actually want to start this on the task. We will
1401                // bring the task to the front, and possibly give it a new intent.
1402            } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1403                mAddingToTask = false;
1404
1405            } else {
1406                mAddingToTask = true;
1407            }
1408
1409            mReuseTask = mInTask;
1410        } else {
1411            mInTask = null;
1412            // Launch ResolverActivity in the source task, so that it stays in the task bounds
1413            // when in freeform workspace.
1414            // Also put noDisplay activities in the source task. These by itself can be placed
1415            // in any task/stack, however it could launch other activities like ResolverActivity,
1416            // and we want those to stay in the original task.
1417            if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1418                    && mSourceRecord.isFreeform())  {
1419                mAddingToTask = true;
1420            }
1421        }
1422
1423        if (mInTask == null) {
1424            if (mSourceRecord == null) {
1425                // This activity is not being started from another...  in this
1426                // case we -always- start a new task.
1427                if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1428                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1429                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1430                    mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1431                }
1432            } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1433                // The original activity who is starting us is running as a single
1434                // instance...  this new activity it is starting must go on its
1435                // own task.
1436                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1437            } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1438                // The activity being started is a single instance...  it always
1439                // gets launched into its own task.
1440                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1441            }
1442        }
1443    }
1444
1445    private void computeSourceStack() {
1446        if (mSourceRecord == null) {
1447            mSourceStack = null;
1448            return;
1449        }
1450        if (!mSourceRecord.finishing) {
1451            mSourceStack = mSourceRecord.task.stack;
1452            return;
1453        }
1454
1455        // If the source is finishing, we can't further count it as our source. This is because the
1456        // task it is associated with may now be empty and on its way out, so we don't want to
1457        // blindly throw it in to that task.  Instead we will take the NEW_TASK flow and try to find
1458        // a task for it. But save the task information so it can be used when creating the new task.
1459        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1460            Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1461                    + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1462            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1463            mNewTaskInfo = mSourceRecord.info;
1464            mNewTaskIntent = mSourceRecord.task.intent;
1465        }
1466        mSourceRecord = null;
1467        mSourceStack = null;
1468    }
1469
1470    /**
1471     * Decide whether the new activity should be inserted into an existing task. Returns null
1472     * if not or an ActivityRecord with the task into which the new activity should be added.
1473     */
1474    private ActivityRecord getReusableIntentActivity() {
1475        // We may want to try to place the new activity in to an existing task.  We always
1476        // do this if the target activity is singleTask or singleInstance; we will also do
1477        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1478        // us to still place it in a new task: multi task, always doc mode, or being asked to
1479        // launch this as a new task behind the current one.
1480        boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1481                (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1482                || mLaunchSingleInstance || mLaunchSingleTask;
1483        // If bring to front is requested, and no result is requested and we have not been given
1484        // an explicit task to launch in to, and we can find a task that was started with this
1485        // same component, then instead of launching bring that one to the front.
1486        putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1487        ActivityRecord intentActivity = null;
1488        if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1489            final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1490            intentActivity = task != null ? task.getTopActivity() : null;
1491        } else if (putIntoExistingTask) {
1492            if (mLaunchSingleInstance) {
1493                // There can be one and only one instance of single instance activity in the
1494                // history, and it is always in its own unique task, so we do a special search.
1495               intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
1496            } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1497                // For the launch adjacent case we only want to put the activity in an existing
1498                // task if the activity already exists in the history.
1499                intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1500                        !mLaunchSingleTask);
1501            } else {
1502                // Otherwise find the best task to put the activity in.
1503                intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1504            }
1505        }
1506        return intentActivity;
1507    }
1508
1509    private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1510        mTargetStack = intentActivity.task.stack;
1511        mTargetStack.mLastPausedActivity = null;
1512        // If the target task is not in the front, then we need to bring it to the front...
1513        // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1514        // the same behavior as if a new instance was being started, which means not bringing it
1515        // to the front if the caller is not itself in the front.
1516        final ActivityStack focusStack = mSupervisor.getFocusedStack();
1517        ActivityRecord curTop = (focusStack == null)
1518                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1519
1520        if (curTop != null
1521                && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1522                && !mAvoidMoveToFront) {
1523            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1524            if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1525                    mSourceStack.topActivity().task == mSourceRecord.task)) {
1526                // We really do want to push this one into the user's face, right now.
1527                if (mLaunchTaskBehind && mSourceRecord != null) {
1528                    intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1529                }
1530                mMovedOtherTask = true;
1531
1532                // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1533                // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1534                // So no point resuming any of the activities here, it just wastes one extra
1535                // resuming, plus enter AND exit transitions.
1536                // Here we only want to bring the target stack forward. Transition will be applied
1537                // to the new activity that's started after the old ones are gone.
1538                final boolean willClearTask =
1539                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1540                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1541                if (!willClearTask) {
1542                    final ActivityStack launchStack = getLaunchStack(
1543                            mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
1544                    if (launchStack == null || launchStack == mTargetStack) {
1545                        // We only want to move to the front, if we aren't going to launch on a
1546                        // different stack. If we launch on a different stack, we will put the
1547                        // task on top there.
1548                        mTargetStack.moveTaskToFrontLocked(
1549                                intentActivity.task, mNoAnimation, mOptions,
1550                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1551                        mMovedToFront = true;
1552                    } else if (launchStack.mStackId == DOCKED_STACK_ID
1553                            || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1554                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1555                            // If we want to launch adjacent and mTargetStack is not the computed
1556                            // launch stack - move task to top of computed stack.
1557                            mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1558                                    launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1559                                    ANIMATE);
1560                        } else {
1561                            // TODO: This should be reevaluated in MW v2.
1562                            // We choose to move task to front instead of launching it adjacent
1563                            // when specific stack was requested explicitly and it appeared to be
1564                            // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1565                            mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1566                                    mOptions, mStartActivity.appTimeTracker,
1567                                    "bringToFrontInsteadOfAdjacentLaunch");
1568                        }
1569                        mMovedToFront = true;
1570                    }
1571                    mOptions = null;
1572                }
1573                updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
1574            }
1575        }
1576        if (!mMovedToFront && mDoResume) {
1577            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1578                    + " from " + intentActivity);
1579            mTargetStack.moveToFront("intentActivityFound");
1580        }
1581
1582        mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1583                mTargetStack.mStackId);
1584
1585        // If the caller has requested that the target task be reset, then do so.
1586        if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1587            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1588        }
1589        return intentActivity;
1590    }
1591
1592    private void updateTaskReturnToType(
1593            TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1594        if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1595                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1596            // Caller wants to appear on home activity.
1597            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1598            return;
1599        } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1600            // Task will be launched over the home stack, so return home.
1601            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1602            return;
1603        }
1604
1605        // Else we are coming from an application stack so return to an application.
1606        task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1607    }
1608
1609    private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1610        if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1611                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1612            // The caller has requested to completely replace any existing task with its new
1613            // activity. Well that should not be too hard...
1614            mReuseTask = intentActivity.task;
1615            mReuseTask.performClearTaskLocked();
1616            mReuseTask.setIntent(mStartActivity);
1617            // When we clear the task - focus will be adjusted, which will bring another task
1618            // to top before we launch the activity we need. This will temporary swap their
1619            // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1620            mMovedOtherTask = true;
1621        } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1622                || mLaunchSingleInstance || mLaunchSingleTask) {
1623            ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1624                    mLaunchFlags);
1625            if (top == null) {
1626                // A special case: we need to start the activity because it is not currently
1627                // running, and the caller has asked to clear the current task to have this
1628                // activity at the top.
1629                mAddingToTask = true;
1630                // Now pretend like this activity is being started by the top of its task, so it
1631                // is put in the right place.
1632                mSourceRecord = intentActivity;
1633                final TaskRecord task = mSourceRecord.task;
1634                if (task != null && task.stack == null) {
1635                    // Target stack got cleared when we all activities were removed above.
1636                    // Go ahead and reset it.
1637                    mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1638                            null /* bounds */, mLaunchFlags, mOptions);
1639                    mTargetStack.addTask(task,
1640                            !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1641                }
1642            }
1643        } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1644            // In this case the top activity on the task is the same as the one being launched,
1645            // so we take that as a request to bring the task to the foreground. If the top
1646            // activity in the task is the root activity, deliver this new intent to it if it
1647            // desires.
1648            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1649                    && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1650                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1651                        intentActivity.task);
1652                if (intentActivity.frontOfTask) {
1653                    intentActivity.task.setIntent(mStartActivity);
1654                }
1655                intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1656                        mStartActivity.launchedFromPackage);
1657            } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
1658                // In this case we are launching the root activity of the task, but with a
1659                // different intent. We should start a new instance on top.
1660                mAddingToTask = true;
1661                mSourceRecord = intentActivity;
1662            }
1663        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1664            // In this case an activity is being launched in to an existing task, without
1665            // resetting that task. This is typically the situation of launching an activity
1666            // from a notification or shortcut. We want to place the new activity on top of the
1667            // current task.
1668            mAddingToTask = true;
1669            mSourceRecord = intentActivity;
1670        } else if (!intentActivity.task.rootWasReset) {
1671            // In this case we are launching into an existing task that has not yet been started
1672            // from its front door. The current task has been brought to the front. Ideally,
1673            // we'd probably like to place this new task at the bottom of its stack, but that's
1674            // a little hard to do with the current organization of the code so for now we'll
1675            // just drop it.
1676            intentActivity.task.setIntent(mStartActivity);
1677        }
1678    }
1679
1680    private void resumeTargetStackIfNeeded() {
1681        if (mDoResume) {
1682            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1683            if (!mMovedToFront) {
1684                // Make sure to notify Keyguard as well if we are not running an app transition
1685                // later.
1686                mSupervisor.notifyActivityDrawnForKeyguard();
1687            }
1688        } else {
1689            ActivityOptions.abort(mOptions);
1690        }
1691        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1692    }
1693
1694    private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1695        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1696                mOptions);
1697
1698        if (mReuseTask == null) {
1699            final TaskRecord task = mTargetStack.createTaskRecord(
1700                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1701                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1702                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1703                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1704            mStartActivity.setTask(task, taskToAffiliate);
1705            if (mLaunchBounds != null) {
1706                final int stackId = mTargetStack.mStackId;
1707                if (StackId.resizeStackWithLaunchBounds(stackId)) {
1708                    mService.resizeStack(
1709                            stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1710                } else {
1711                    mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1712                }
1713            }
1714            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1715                    "Starting new activity " +
1716                            mStartActivity + " in new task " + mStartActivity.task);
1717        } else {
1718            mStartActivity.setTask(mReuseTask, taskToAffiliate);
1719        }
1720    }
1721
1722    private int setTaskFromSourceRecord() {
1723        final TaskRecord sourceTask = mSourceRecord.task;
1724        // We only want to allow changing stack if the target task is not the top one,
1725        // otherwise we would move the launching task to the other side, rather than show
1726        // two side by side.
1727        final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1728        if (moveStackAllowed) {
1729            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1730                    mOptions);
1731        }
1732
1733        if (mTargetStack == null) {
1734            mTargetStack = sourceTask.stack;
1735        } else if (mTargetStack != sourceTask.stack) {
1736            mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1737                    ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1738        }
1739        if (mDoResume) {
1740            mTargetStack.moveToFront("sourceStackToFront");
1741        }
1742        final TaskRecord topTask = mTargetStack.topTask();
1743        if (topTask != sourceTask && !mAvoidMoveToFront) {
1744            mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1745                    mStartActivity.appTimeTracker, "sourceTaskToFront");
1746        }
1747        if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1748            // In this case, we are adding the activity to an existing task, but the caller has
1749            // asked to clear that task if the activity is already running.
1750            ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1751            mKeepCurTransition = true;
1752            if (top != null) {
1753                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1754                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1755                // For paranoia, make sure we have correctly resumed the top activity.
1756                mTargetStack.mLastPausedActivity = null;
1757                if (mDoResume) {
1758                    mSupervisor.resumeFocusedStackTopActivityLocked();
1759                }
1760                ActivityOptions.abort(mOptions);
1761                return START_DELIVERED_TO_TOP;
1762            }
1763        } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1764            // In this case, we are launching an activity in our own task that may already be
1765            // running somewhere in the history, and we want to shuffle it to the front of the
1766            // stack if so.
1767            final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1768            if (top != null) {
1769                final TaskRecord task = top.task;
1770                task.moveActivityToFrontLocked(top);
1771                top.updateOptionsLocked(mOptions);
1772                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1773                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1774                mTargetStack.mLastPausedActivity = null;
1775                if (mDoResume) {
1776                    mSupervisor.resumeFocusedStackTopActivityLocked();
1777                }
1778                return START_DELIVERED_TO_TOP;
1779            }
1780        }
1781
1782        // An existing activity is starting this new activity, so we want to keep the new one in
1783        // the same task as the one that is starting it.
1784        mStartActivity.setTask(sourceTask, null);
1785        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1786                + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1787        return START_SUCCESS;
1788    }
1789
1790    private int setTaskFromInTask() {
1791        if (mLaunchBounds != null) {
1792            mInTask.updateOverrideConfiguration(mLaunchBounds);
1793            int stackId = mInTask.getLaunchStackId();
1794            if (stackId != mInTask.stack.mStackId) {
1795                final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
1796                        mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1797                stackId = stack.mStackId;
1798            }
1799            if (StackId.resizeStackWithLaunchBounds(stackId)) {
1800                mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1801            }
1802        }
1803        mTargetStack = mInTask.stack;
1804        mTargetStack.moveTaskToFrontLocked(
1805                mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1806
1807        // Check whether we should actually launch the new activity in to the task,
1808        // or just reuse the current activity on top.
1809        ActivityRecord top = mInTask.getTopActivity();
1810        if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1811            if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1812                    || mLaunchSingleTop || mLaunchSingleTask) {
1813                ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1814                if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1815                    // We don't need to start a new activity, and the client said not to do
1816                    // anything if that is the case, so this is it!
1817                    return START_RETURN_INTENT_TO_CALLER;
1818                }
1819                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1820                return START_DELIVERED_TO_TOP;
1821            }
1822        }
1823
1824        if (!mAddingToTask) {
1825            // We don't actually want to have this activity added to the task, so just
1826            // stop here but still tell the caller that we consumed the intent.
1827            ActivityOptions.abort(mOptions);
1828            return START_TASK_TO_FRONT;
1829        }
1830
1831        mStartActivity.setTask(mInTask, null);
1832        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1833                "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1834
1835        return START_SUCCESS;
1836    }
1837
1838    private void setTaskToCurrentTopOrCreateNewTask() {
1839        mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1840                mOptions);
1841        if (mDoResume) {
1842            mTargetStack.moveToFront("addingToTopTask");
1843        }
1844        final ActivityRecord prev = mTargetStack.topActivity();
1845        final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1846                        mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1847                        mStartActivity.info, mIntent, null, null, true);
1848        mStartActivity.setTask(task, null);
1849        mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1850        if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1851                "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1852    }
1853
1854    private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1855            boolean launchSingleTask, int launchFlags) {
1856        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1857                (launchSingleInstance || launchSingleTask)) {
1858            // We have a conflict between the Intent and the Activity manifest, manifest wins.
1859            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1860                    "\"singleInstance\" or \"singleTask\"");
1861            launchFlags &=
1862                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1863        } else {
1864            switch (r.info.documentLaunchMode) {
1865                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1866                    break;
1867                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1868                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1869                    break;
1870                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1871                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1872                    break;
1873                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1874                    launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1875                    break;
1876            }
1877        }
1878        return launchFlags;
1879    }
1880
1881    final void doPendingActivityLaunchesLocked(boolean doResume) {
1882        while (!mPendingActivityLaunches.isEmpty()) {
1883            final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1884            final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
1885            try {
1886                final int result = startActivityUnchecked(
1887                        pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1888                postStartActivityUncheckedProcessing(
1889                        pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1890                        mTargetStack);
1891            } catch (Exception e) {
1892                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1893                pal.sendErrorResult(e.getMessage());
1894            }
1895        }
1896    }
1897
1898    private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1899            int launchFlags, ActivityOptions aOptions) {
1900        final TaskRecord task = r.task;
1901        if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1902            return mSupervisor.mHomeStack;
1903        }
1904
1905        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
1906        if (stack != null) {
1907            return stack;
1908        }
1909
1910        if (task != null && task.stack != null) {
1911            stack = task.stack;
1912            if (stack.isOnHomeDisplay()) {
1913                if (mSupervisor.mFocusedStack != stack) {
1914                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1915                            "computeStackFocus: Setting " + "focused stack to r=" + r
1916                                    + " task=" + task);
1917                } else {
1918                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1919                            "computeStackFocus: Focused stack already="
1920                                    + mSupervisor.mFocusedStack);
1921                }
1922            }
1923            return stack;
1924        }
1925
1926        final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1927        if (container != null) {
1928            // The first time put it on the desired stack, after this put on task stack.
1929            r.mInitialActivityContainer = null;
1930            return container.mStack;
1931        }
1932
1933        // The fullscreen stack can contain any task regardless of if the task is resizeable
1934        // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1935        // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1936        // we can also put it in the focused stack.
1937        final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1938        final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1939                || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1940                || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
1941        if (canUseFocusedStack && (!newTask
1942                || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1943            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1944                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1945            return mSupervisor.mFocusedStack;
1946        }
1947
1948        // We first try to put the task in the first dynamic stack.
1949        final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1950        for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1951            stack = homeDisplayStacks.get(stackNdx);
1952            if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1953                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1954                        "computeStackFocus: Setting focused stack=" + stack);
1955                return stack;
1956            }
1957        }
1958
1959        // If there is no suitable dynamic stack then we figure out which static stack to use.
1960        final int stackId = task != null ? task.getLaunchStackId() :
1961                bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1962                        FULLSCREEN_WORKSPACE_STACK_ID;
1963        stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1964        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1965                + r + " stackId=" + stack.mStackId);
1966        return stack;
1967    }
1968
1969    private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1970            ActivityOptions aOptions) {
1971
1972        // We are reusing a task, keep the stack!
1973        if (mReuseTask != null) {
1974            return mReuseTask.stack;
1975        }
1976
1977        final int launchStackId =
1978                (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1979
1980        if (isValidLaunchStackId(launchStackId, r)) {
1981            return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
1982        } else if (launchStackId == DOCKED_STACK_ID) {
1983            // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1984            // for this activity, so we put the activity in the fullscreen stack.
1985            return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1986        }
1987
1988        if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
1989            return null;
1990        }
1991        // Otherwise handle adjacent launch.
1992
1993        // The parent activity doesn't want to launch the activity on top of itself, but
1994        // instead tries to put it onto other side in side-by-side mode.
1995        final ActivityStack parentStack = task != null ? task.stack
1996                : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1997                : mSupervisor.mFocusedStack;
1998
1999        if (parentStack != mSupervisor.mFocusedStack) {
2000            // If task's parent stack is not focused - use it during adjacent launch.
2001            return parentStack;
2002        } else {
2003            if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2004                // If task is already on top of focused stack - use it. We don't want to move the
2005                // existing focused task to adjacent stack, just deliver new intent in this case.
2006                return mSupervisor.mFocusedStack;
2007            }
2008
2009            if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2010                // If parent was in docked stack, the natural place to launch another activity
2011                // will be fullscreen, so it can appear alongside the docked window.
2012                return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2013                        ON_TOP);
2014            } else {
2015                // If the parent is not in the docked stack, we check if there is docked window
2016                // and if yes, we will launch into that stack. If not, we just put the new
2017                // activity into parent's stack, because we can't find a better place.
2018                final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2019                if (dockedStack != null
2020                        && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2021                    // There is a docked stack, but it isn't visible, so we can't launch into that.
2022                    return null;
2023                } else {
2024                    return dockedStack;
2025                }
2026            }
2027        }
2028    }
2029
2030    private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2031        if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2032                || !StackId.isStaticStack(stackId)) {
2033            return false;
2034        }
2035
2036        if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2037                && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2038            return false;
2039        }
2040
2041        if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2042            return true;
2043        }
2044
2045        if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2046            return false;
2047        }
2048
2049        final boolean supportsPip = mService.mSupportsPictureInPicture
2050                && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2051        if (stackId == PINNED_STACK_ID && !supportsPip) {
2052            return false;
2053        }
2054        return true;
2055    }
2056
2057    Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2058        Rect newBounds = null;
2059        if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2060            if (mSupervisor.canUseActivityOptionsLaunchBounds(
2061                    options, options.getLaunchStackId())) {
2062                newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2063            }
2064        }
2065        return newBounds;
2066    }
2067
2068    void setWindowManager(WindowManagerService wm) {
2069        mWindowManager = wm;
2070    }
2071
2072    void removePendingActivityLaunchesLocked(ActivityStack stack) {
2073        for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2074            PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2075            if (pal.stack == stack) {
2076                mPendingActivityLaunches.remove(palNdx);
2077            }
2078        }
2079    }
2080}
2081