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