2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.am;
19 import static android.app.Activity.RESULT_CANCELED;
20 import static android.app.ActivityManager.START_ABORTED;
21 import static android.app.ActivityManager.START_CANCELED;
22 import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
23 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
24 import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
25 import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
26 import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
27 import static android.app.ActivityManager.START_SUCCESS;
28 import static android.app.ActivityManager.START_TASK_TO_FRONT;
29 import static android.app.ActivityManager.StackId;
30 import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
31 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
32 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
33 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
34 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
35 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
36 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
37 import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
38 import static android.app.ActivityManager.StackId.isDynamicStack;
39 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
40 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
41 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
42 import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
43 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
44 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
45 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
46 import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
47 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
48 import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
49 import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
50 import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
51 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
52 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
53 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
54 import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
55 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
56 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
57 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
58 import static android.view.Display.DEFAULT_DISPLAY;
59 import static android.view.Display.INVALID_DISPLAY;
60 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
61 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
62 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
63 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
64 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
65 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
66 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
67 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
68 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
69 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
70 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
71 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
72 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
73 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
74 import static com.android.server.am.ActivityManagerService.ANIMATE;
75 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
76 import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
77 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
78 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
79 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
80 import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
81 import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
82 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
83 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
84 import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
85 import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
86 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
87 import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
89 import android.annotation.NonNull;
90 import android.app.ActivityManager;
91 import android.app.ActivityOptions;
92 import android.app.AppGlobals;
93 import android.app.IActivityContainer;
94 import android.app.IApplicationThread;
95 import android.app.PendingIntent;
96 import android.app.ProfilerInfo;
97 import android.app.WaitResult;
98 import android.content.ComponentName;
99 import android.content.IIntentSender;
100 import android.content.Intent;
101 import android.content.IntentSender;
102 import android.content.pm.ActivityInfo;
103 import android.content.pm.ApplicationInfo;
104 import android.content.pm.AuxiliaryResolveInfo;
105 import android.content.pm.PackageManager;
106 import android.content.pm.ResolveInfo;
107 import android.content.pm.UserInfo;
108 import android.content.res.Configuration;
109 import android.graphics.Rect;
110 import android.hardware.power.V1_0.PowerHint;
111 import android.os.Binder;
112 import android.os.Bundle;
113 import android.os.IBinder;
114 import android.os.RemoteException;
115 import android.os.SystemClock;
116 import android.os.UserHandle;
117 import android.os.UserManager;
118 import android.service.voice.IVoiceInteractionSession;
119 import android.text.TextUtils;
120 import android.util.EventLog;
121 import android.util.Slog;
123 import com.android.internal.app.HeavyWeightSwitcherActivity;
124 import com.android.internal.app.IVoiceInteractor;
125 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
126 import com.android.server.pm.InstantAppResolver;
127 import com.android.server.wm.WindowManagerService;
129 import java.io.PrintWriter;
130 import java.text.DateFormat;
131 import java.util.ArrayList;
132 import java.util.Date;
135 * Controller for interpreting how and then launching activities.
137 * This class collects all the logic for determining how an intent and flags should be turned into
138 * an activity and associated task and stack.
140 class ActivityStarter {
141 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
142 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
143 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
144 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
145 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
147 private final ActivityManagerService mService;
148 private final ActivityStackSupervisor mSupervisor;
149 private ActivityStartInterceptor mInterceptor;
150 private WindowManagerService mWindowManager;
152 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
154 // Share state variable among methods when starting an activity.
155 private ActivityRecord mStartActivity;
156 private Intent mIntent;
157 private int mCallingUid;
158 private ActivityOptions mOptions;
160 private boolean mLaunchSingleTop;
161 private boolean mLaunchSingleInstance;
162 private boolean mLaunchSingleTask;
163 private boolean mLaunchTaskBehind;
164 private int mLaunchFlags;
166 private Rect mLaunchBounds;
168 private ActivityRecord mNotTop;
169 private boolean mDoResume;
170 private int mStartFlags;
171 private ActivityRecord mSourceRecord;
172 private int mSourceDisplayId;
174 private TaskRecord mInTask;
175 private boolean mAddingToTask;
176 private TaskRecord mReuseTask;
178 private ActivityInfo mNewTaskInfo;
179 private Intent mNewTaskIntent;
180 private ActivityStack mSourceStack;
181 private ActivityStack mTargetStack;
182 // Indicates that we moved other task and are going to put something on top soon, so
183 // we don't want to show it redundantly or accidentally change what's shown below.
184 private boolean mMovedOtherTask;
185 private boolean mMovedToFront;
186 private boolean mNoAnimation;
187 private boolean mKeepCurTransition;
188 private boolean mAvoidMoveToFront;
189 private boolean mPowerHintSent;
191 private IVoiceInteractionSession mVoiceSession;
192 private IVoiceInteractor mVoiceInteractor;
194 private boolean mUsingVr2dDisplay;
196 // Last home activity record we attempted to start
197 private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
198 // The result of the last home activity we attempted to start.
199 private int mLastHomeActivityStartResult;
200 // Last activity record we attempted to start
201 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
202 // The result of the last activity we attempted to start.
203 private int mLastStartActivityResult;
204 // Time in milli seconds we attempted to start the last activity.
205 private long mLastStartActivityTimeMs;
206 // The reason we were trying to start the last activity
207 private String mLastStartReason;
209 private void reset() {
210 mStartActivity = null;
215 mLaunchSingleTop = false;
216 mLaunchSingleInstance = false;
217 mLaunchSingleTask = false;
218 mLaunchTaskBehind = false;
221 mLaunchBounds = null;
226 mSourceRecord = null;
227 mSourceDisplayId = INVALID_DISPLAY;
230 mAddingToTask = false;
234 mNewTaskIntent = null;
238 mMovedOtherTask = false;
239 mMovedToFront = false;
240 mNoAnimation = false;
241 mKeepCurTransition = false;
242 mAvoidMoveToFront = false;
244 mVoiceSession = null;
245 mVoiceInteractor = null;
247 mUsingVr2dDisplay = false;
250 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
252 mSupervisor = supervisor;
253 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
254 mUsingVr2dDisplay = false;
257 int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
258 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
259 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
260 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
261 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
262 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
263 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
264 TaskRecord inTask, String reason) {
266 if (TextUtils.isEmpty(reason)) {
267 throw new IllegalArgumentException("Need to specify a reason.");
269 mLastStartReason = reason;
270 mLastStartActivityTimeMs = System.currentTimeMillis();
271 mLastStartActivityRecord[0] = null;
273 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
274 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
275 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
276 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
279 if (outActivity != null) {
280 // mLastStartActivityRecord[0] is set in the call to startActivity above.
281 outActivity[0] = mLastStartActivityRecord[0];
284 // Aborted results are treated as successes externally, but we must track them internally.
285 return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
288 /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
289 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
290 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
291 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
292 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
293 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
294 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
295 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
297 int err = ActivityManager.START_SUCCESS;
298 // Pull the optional Ephemeral Installer-only bundle out of the options early.
299 final Bundle verificationBundle
300 = options != null ? options.popAppVerificationBundle() : null;
302 ProcessRecord callerApp = null;
303 if (caller != null) {
304 callerApp = mService.getRecordForAppLocked(caller);
305 if (callerApp != null) {
306 callingPid = callerApp.pid;
307 callingUid = callerApp.info.uid;
309 Slog.w(TAG, "Unable to find app for caller " + caller
310 + " (pid=" + callingPid + ") when starting: "
311 + intent.toString());
312 err = ActivityManager.START_PERMISSION_DENIED;
316 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
318 if (err == ActivityManager.START_SUCCESS) {
319 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
320 + "} from uid " + callingUid);
323 ActivityRecord sourceRecord = null;
324 ActivityRecord resultRecord = null;
325 if (resultTo != null) {
326 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
327 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
328 "Will send result to " + resultTo + " " + sourceRecord);
329 if (sourceRecord != null) {
330 if (requestCode >= 0 && !sourceRecord.finishing) {
331 resultRecord = sourceRecord;
336 final int launchFlags = intent.getFlags();
338 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
339 // Transfer the result target from the source activity to the new
340 // one being started, including any failures.
341 if (requestCode >= 0) {
342 ActivityOptions.abort(options);
343 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
345 resultRecord = sourceRecord.resultTo;
346 if (resultRecord != null && !resultRecord.isInStackLocked()) {
349 resultWho = sourceRecord.resultWho;
350 requestCode = sourceRecord.requestCode;
351 sourceRecord.resultTo = null;
352 if (resultRecord != null) {
353 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
355 if (sourceRecord.launchedFromUid == callingUid) {
356 // The new activity is being launched from the same uid as the previous
357 // activity in the flow, and asking to forward its result back to the
358 // previous. In this case the activity is serving as a trampoline between
359 // the two, so we also want to update its launchedFromPackage to be the
360 // same as the previous activity. Note that this is safe, since we know
361 // these two packages come from the same uid; the caller could just as
362 // well have supplied that same package name itself. This specifially
363 // deals with the case of an intent picker/chooser being launched in the app
364 // flow to redirect to an activity picked by the user, where we want the final
365 // activity to consider it to have been launched by the previous app activity.
366 callingPackage = sourceRecord.launchedFromPackage;
370 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
371 // We couldn't find a class that can handle the given Intent.
372 // That's the end of that!
373 err = ActivityManager.START_INTENT_NOT_RESOLVED;
376 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
377 // We couldn't find the specific class specified in the Intent.
378 // Also the end of the line.
379 err = ActivityManager.START_CLASS_NOT_FOUND;
382 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
383 && sourceRecord.getTask().voiceSession != null) {
384 // If this activity is being launched as part of a voice session, we need
385 // to ensure that it is safe to do so. If the upcoming activity will also
386 // be part of the voice session, we can only launch it if it has explicitly
387 // said it supports the VOICE category, or it is a part of the calling app.
388 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
389 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
391 intent.addCategory(Intent.CATEGORY_VOICE);
392 if (!AppGlobals.getPackageManager().activitySupportsIntent(
393 intent.getComponent(), intent, resolvedType)) {
395 "Activity being started in current voice task does not support voice: "
397 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
399 } catch (RemoteException e) {
400 Slog.w(TAG, "Failure checking voice capabilities", e);
401 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
406 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
407 // If the caller is starting a new voice session, just make sure the target
408 // is actually allowing it to run this way.
410 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
411 intent, resolvedType)) {
413 "Activity being started in new voice task does not support: "
415 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
417 } catch (RemoteException e) {
418 Slog.w(TAG, "Failure checking voice capabilities", e);
419 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
423 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
425 if (err != START_SUCCESS) {
426 if (resultRecord != null) {
427 resultStack.sendActivityResultLocked(
428 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
430 ActivityOptions.abort(options);
434 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
435 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
436 resultRecord, resultStack, options);
437 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
438 callingPid, resolvedType, aInfo.applicationInfo);
440 if (mService.mController != null) {
442 // The Intent we give to the watcher has the extra data
443 // stripped off, since it can contain private information.
444 Intent watchIntent = intent.cloneFilter();
445 abort |= !mService.mController.activityStarting(watchIntent,
446 aInfo.applicationInfo.packageName);
447 } catch (RemoteException e) {
448 mService.mController = null;
452 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
453 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
455 intent = mInterceptor.mIntent;
456 rInfo = mInterceptor.mRInfo;
457 aInfo = mInterceptor.mAInfo;
458 resolvedType = mInterceptor.mResolvedType;
459 inTask = mInterceptor.mInTask;
460 callingPid = mInterceptor.mCallingPid;
461 callingUid = mInterceptor.mCallingUid;
462 options = mInterceptor.mActivityOptions;
464 if (resultRecord != null) {
465 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
466 RESULT_CANCELED, null);
468 // We pretend to the caller that it was really started, but
469 // they will just get a cancel result.
470 ActivityOptions.abort(options);
471 return START_ABORTED;
474 // If permissions need a review before any of the app components can run, we
475 // launch the review activity and pass a pending intent to start the activity
476 // we are to launching now after the review is completed.
477 if (mService.mPermissionReviewRequired && aInfo != null) {
478 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
479 aInfo.packageName, userId)) {
480 IIntentSender target = mService.getIntentSenderLocked(
481 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
482 callingUid, userId, null, null, 0, new Intent[]{intent},
483 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
484 | PendingIntent.FLAG_ONE_SHOT, null);
486 final int flags = intent.getFlags();
487 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
488 newIntent.setFlags(flags
489 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
490 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
491 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
492 if (resultRecord != null) {
493 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
498 callingUid = realCallingUid;
499 callingPid = realCallingPid;
501 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
502 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
503 null /*profilerInfo*/);
505 if (DEBUG_PERMISSIONS_REVIEW) {
506 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
507 true, false) + "} from uid " + callingUid + " on display "
508 + (container == null ? (mSupervisor.mFocusedStack == null ?
509 DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
510 (container.mActivityDisplay == null ? DEFAULT_DISPLAY :
511 container.mActivityDisplay.mDisplayId)));
516 // If we have an ephemeral app, abort the process of launching the resolved intent.
517 // Instead, launch the ephemeral installer. Once the installer is finished, it
518 // starts either the intent we resolved here [on install error] or the ephemeral
519 // app [on install success].
520 if (rInfo != null && rInfo.auxiliaryInfo != null) {
521 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
522 callingPackage, verificationBundle, resolvedType, userId);
524 callingUid = realCallingUid;
525 callingPid = realCallingPid;
527 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
530 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
531 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
532 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
533 mSupervisor, container, options, sourceRecord);
534 if (outActivity != null) {
538 if (r.appTimeTracker == null && sourceRecord != null) {
539 // If the caller didn't specify an explicit time tracker, we want to continue
540 // tracking under any it has.
541 r.appTimeTracker = sourceRecord.appTimeTracker;
544 final ActivityStack stack = mSupervisor.mFocusedStack;
545 if (voiceSession == null && (stack.mResumedActivity == null
546 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
547 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
548 realCallingPid, realCallingUid, "Activity start")) {
549 PendingActivityLaunch pal = new PendingActivityLaunch(r,
550 sourceRecord, startFlags, stack, callerApp);
551 mPendingActivityLaunches.add(pal);
552 ActivityOptions.abort(options);
553 return ActivityManager.START_SWITCHES_CANCELED;
557 if (mService.mDidAppSwitch) {
558 // This is the second allowed switch since we stopped switches,
559 // so now just generally allow switches. Use case: user presses
560 // home (switches disabled, switch to home, mDidAppSwitch now true);
561 // user taps a home icon (coming from home so allowed, we hit here
562 // and now allow anyone to switch again).
563 mService.mAppSwitchesAllowedTime = 0;
565 mService.mDidAppSwitch = true;
568 doPendingActivityLaunchesLocked(false);
570 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
571 options, inTask, outActivity);
575 * Creates a launch intent for the given auxiliary resolution data.
577 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
578 Intent originalIntent, String callingPackage, Bundle verificationBundle,
579 String resolvedType, int userId) {
580 if (auxiliaryResponse.needsPhaseTwo) {
581 // request phase two resolution
582 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
583 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
584 verificationBundle, userId);
586 return InstantAppResolver.buildEphemeralInstallerIntent(
587 Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
588 auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
589 resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
590 auxiliaryResponse.versionCode, auxiliaryResponse.token,
591 auxiliaryResponse.needsPhaseTwo);
594 void postStartActivityProcessing(
595 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
596 ActivityStack targetStack) {
598 if (ActivityManager.isStartResultFatalError(result)) {
602 // We're waiting for an activity launch to finish, but that activity simply
603 // brought another activity to front. Let startActivityMayWait() know about
604 // this, so it waits for the new activity to become visible instead.
605 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
606 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
609 int startedActivityStackId = INVALID_STACK_ID;
610 final ActivityStack currentStack = r.getStack();
611 if (currentStack != null) {
612 startedActivityStackId = currentStack.mStackId;
613 } else if (mTargetStack != null) {
614 startedActivityStackId = targetStack.mStackId;
617 if (startedActivityStackId == DOCKED_STACK_ID) {
618 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
619 final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
620 if (homeStackVisible) {
621 // We launch an activity while being in home stack, which means either launcher or
622 // recents into docked stack. We don't want the launched activity to be alone in a
623 // docked stack, so we want to immediately launch recents too.
624 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
625 mWindowManager.showRecentApps(true /* fromHome */);
630 boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
631 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
632 if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
633 || result == START_DELIVERED_TO_TOP || clearedTask)) {
634 // The activity was already running in the pinned stack so it wasn't started, but either
635 // brought to the front or the new intent was delivered to it since it was already in
636 // front. Notify anyone interested in this piece of information.
637 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
643 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
644 mSupervisor.moveHomeStackTaskToTop(reason);
645 mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
646 null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
647 null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
648 null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
649 null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
650 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
651 false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
652 null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
653 if (mSupervisor.inResumeTopActivity) {
654 // If we are in resume section already, home activity will be initialized, but not
655 // resumed (to avoid recursive resume) and will stay that way until something pokes it
656 // again. We need to schedule another resume.
657 mSupervisor.scheduleResumeTopActivities();
661 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
662 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
663 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
664 FLAG_ACTIVITY_TASK_ON_HOME);
665 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
666 : ActivityOptions.makeBasic());
667 options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
668 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
671 final int startActivityMayWait(IApplicationThread caller, int callingUid,
672 String callingPackage, Intent intent, String resolvedType,
673 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
674 IBinder resultTo, String resultWho, int requestCode, int startFlags,
675 ProfilerInfo profilerInfo, WaitResult outResult,
676 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
677 IActivityContainer iContainer, TaskRecord inTask, String reason) {
678 // Refuse possible leaked file descriptors
679 if (intent != null && intent.hasFileDescriptors()) {
680 throw new IllegalArgumentException("File descriptors passed in Intent");
682 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
683 boolean componentSpecified = intent.getComponent() != null;
685 // Save a copy in case ephemeral needs it
686 final Intent ephemeralIntent = new Intent(intent);
687 // Don't modify the client's object!
688 intent = new Intent(intent);
689 if (componentSpecified
690 && intent.getData() != null
691 && Intent.ACTION_VIEW.equals(intent.getAction())
692 && mService.getPackageManagerInternalLocked()
693 .isInstantAppInstallerComponent(intent.getComponent())) {
694 // intercept intents targeted directly to the ephemeral installer the
695 // ephemeral installer should never be started with a raw URL; instead
696 // adjust the intent so it looks like a "normal" instant app launch
697 intent.setComponent(null /*component*/);
698 componentSpecified = false;
701 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
703 UserInfo userInfo = mSupervisor.getUserInfo(userId);
704 if (userInfo != null && userInfo.isManagedProfile()) {
705 // Special case for managed profiles, if attempting to launch non-cryto aware
706 // app in a locked managed profile from an unlocked parent allow it to resolve
707 // as user will be sent via confirm credentials to unlock the profile.
708 UserManager userManager = UserManager.get(mService.mContext);
709 boolean profileLockedAndParentUnlockingOrUnlocked = false;
710 long token = Binder.clearCallingIdentity();
712 UserInfo parent = userManager.getProfileParent(userId);
713 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
714 && userManager.isUserUnlockingOrUnlocked(parent.id)
715 && !userManager.isUserUnlockingOrUnlocked(userId);
717 Binder.restoreCallingIdentity(token);
719 if (profileLockedAndParentUnlockingOrUnlocked) {
720 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
721 PackageManager.MATCH_DIRECT_BOOT_AWARE
722 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
726 // Collect information about the target of the Intent.
727 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
729 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
730 ActivityStackSupervisor.ActivityContainer container =
731 (ActivityStackSupervisor.ActivityContainer)iContainer;
732 synchronized (mService) {
733 if (container != null && container.mParentActivity != null &&
734 container.mParentActivity.state != RESUMED) {
735 // Cannot start a child activity if the parent is not resumed.
736 return ActivityManager.START_CANCELED;
738 final int realCallingPid = Binder.getCallingPid();
739 final int realCallingUid = Binder.getCallingUid();
741 if (callingUid >= 0) {
743 } else if (caller == null) {
744 callingPid = realCallingPid;
745 callingUid = realCallingUid;
747 callingPid = callingUid = -1;
750 final ActivityStack stack;
751 if (container == null || container.mStack.isOnHomeDisplay()) {
752 stack = mSupervisor.mFocusedStack;
754 stack = container.mStack;
756 stack.mConfigWillChange = globalConfig != null
757 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
758 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
759 "Starting activity when config will change = " + stack.mConfigWillChange);
761 final long origId = Binder.clearCallingIdentity();
764 (aInfo.applicationInfo.privateFlags
765 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
766 // This may be a heavy-weight process! Check to see if we already
767 // have another, different heavy-weight process running.
768 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
769 final ProcessRecord heavy = mService.mHeavyWeightProcess;
770 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
771 || !heavy.processName.equals(aInfo.processName))) {
772 int appCallingUid = callingUid;
773 if (caller != null) {
774 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
775 if (callerApp != null) {
776 appCallingUid = callerApp.info.uid;
778 Slog.w(TAG, "Unable to find app for caller " + caller
779 + " (pid=" + callingPid + ") when starting: "
780 + intent.toString());
781 ActivityOptions.abort(options);
782 return ActivityManager.START_PERMISSION_DENIED;
786 IIntentSender target = mService.getIntentSenderLocked(
787 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
788 appCallingUid, userId, null, null, 0, new Intent[] { intent },
789 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
790 | PendingIntent.FLAG_ONE_SHOT, null);
792 Intent newIntent = new Intent();
793 if (requestCode >= 0) {
794 // Caller is requesting a result.
795 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
797 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
798 new IntentSender(target));
799 if (heavy.activities.size() > 0) {
800 ActivityRecord hist = heavy.activities.get(0);
801 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
803 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
804 hist.getTask().taskId);
806 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
808 newIntent.setFlags(intent.getFlags());
809 newIntent.setClassName("android",
810 HeavyWeightSwitcherActivity.class.getName());
814 callingUid = Binder.getCallingUid();
815 callingPid = Binder.getCallingPid();
816 componentSpecified = true;
817 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
818 aInfo = rInfo != null ? rInfo.activityInfo : null;
820 aInfo = mService.getActivityInfoForUser(aInfo, userId);
826 final ActivityRecord[] outRecord = new ActivityRecord[1];
827 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
828 aInfo, rInfo, voiceSession, voiceInteractor,
829 resultTo, resultWho, requestCode, callingPid,
830 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
831 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
834 Binder.restoreCallingIdentity(origId);
836 if (stack.mConfigWillChange) {
837 // If the caller also wants to switch to a new configuration,
838 // do so now. This allows a clean switch, as we are waiting
839 // for the current activity to pause (so we will not destroy
840 // it), and have not yet started the next activity.
841 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
842 "updateConfiguration()");
843 stack.mConfigWillChange = false;
844 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
845 "Updating to new configuration after starting activity.");
846 mService.updateConfigurationLocked(globalConfig, null, false);
849 if (outResult != null) {
850 outResult.result = res;
851 if (res == ActivityManager.START_SUCCESS) {
852 mSupervisor.mWaitingActivityLaunched.add(outResult);
856 } catch (InterruptedException e) {
858 } while (outResult.result != START_TASK_TO_FRONT
859 && !outResult.timeout && outResult.who == null);
860 if (outResult.result == START_TASK_TO_FRONT) {
861 res = START_TASK_TO_FRONT;
864 if (res == START_TASK_TO_FRONT) {
865 final ActivityRecord r = outRecord[0];
867 // ActivityRecord may represent a different activity, but it should not be in
868 // the resumed state.
869 if (r.nowVisible && r.state == RESUMED) {
870 outResult.timeout = false;
871 outResult.who = r.realActivity;
872 outResult.totalTime = 0;
873 outResult.thisTime = 0;
875 outResult.thisTime = SystemClock.uptimeMillis();
876 mSupervisor.waitActivityVisible(r.realActivity, outResult);
877 // Note: the timeout variable is not currently not ever set.
881 } catch (InterruptedException e) {
883 } while (!outResult.timeout && outResult.who == null);
888 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
893 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
894 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
895 Bundle bOptions, int userId, String reason) {
896 if (intents == null) {
897 throw new NullPointerException("intents is null");
899 if (resolvedTypes == null) {
900 throw new NullPointerException("resolvedTypes is null");
902 if (intents.length != resolvedTypes.length) {
903 throw new IllegalArgumentException("intents are length different than resolvedTypes");
906 final int realCallingPid = Binder.getCallingPid();
907 final int realCallingUid = Binder.getCallingUid();
910 if (callingUid >= 0) {
912 } else if (caller == null) {
913 callingPid = realCallingPid;
914 callingUid = realCallingUid;
916 callingPid = callingUid = -1;
918 final long origId = Binder.clearCallingIdentity();
920 synchronized (mService) {
921 ActivityRecord[] outActivity = new ActivityRecord[1];
922 for (int i=0; i<intents.length; i++) {
923 Intent intent = intents[i];
924 if (intent == null) {
928 // Refuse possible leaked file descriptors
929 if (intent != null && intent.hasFileDescriptors()) {
930 throw new IllegalArgumentException("File descriptors passed in Intent");
933 boolean componentSpecified = intent.getComponent() != null;
935 // Don't modify the client's object!
936 intent = new Intent(intent);
938 // Collect information about the target of the Intent.
939 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
941 // TODO: New, check if this is correct
942 aInfo = mService.getActivityInfoForUser(aInfo, userId);
945 (aInfo.applicationInfo.privateFlags
946 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
947 throw new IllegalArgumentException(
948 "FLAG_CANT_SAVE_STATE not supported here");
951 ActivityOptions options = ActivityOptions.fromBundle(
952 i == intents.length - 1 ? bOptions : null);
953 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
954 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
955 callingPid, callingUid, callingPackage,
956 realCallingPid, realCallingUid, 0,
957 options, false, componentSpecified, outActivity, null, null, reason);
962 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
966 Binder.restoreCallingIdentity(origId);
969 return START_SUCCESS;
972 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
973 boolean sendHint = forceSend;
976 // If not forced, send power hint when the activity's process is different than the
977 // current resumed activity.
978 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
979 sendHint = resumedActivity == null
980 || resumedActivity.app == null
981 || !resumedActivity.app.equals(mStartActivity.app);
984 if (sendHint && mService.mLocalPowerManager != null) {
985 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
986 mPowerHintSent = true;
990 void sendPowerHintForLaunchEndIfNeeded() {
991 // Trigger launch power hint if activity is launched
992 if (mPowerHintSent && mService.mLocalPowerManager != null) {
993 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
994 mPowerHintSent = false;
998 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
999 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1000 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1001 ActivityRecord[] outActivity) {
1002 int result = START_CANCELED;
1004 mService.mWindowManager.deferSurfaceLayout();
1005 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
1006 startFlags, doResume, options, inTask, outActivity);
1008 // If we are not able to proceed, disassociate the activity from the task. Leaving an
1009 // activity in an incomplete state can lead to issues, such as performing operations
1010 // without a window container.
1011 if (!ActivityManager.isStartResultSuccessful(result)
1012 && mStartActivity.getTask() != null) {
1013 mStartActivity.getTask().removeActivity(mStartActivity);
1015 mService.mWindowManager.continueSurfaceLayout();
1018 postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
1024 // Note: This method should only be called from {@link startActivity}.
1025 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1026 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1027 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1028 ActivityRecord[] outActivity) {
1030 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1033 computeLaunchingTaskFlags();
1035 computeSourceStack();
1037 mIntent.setFlags(mLaunchFlags);
1039 ActivityRecord reusedActivity = getReusableIntentActivity();
1041 final int preferredLaunchStackId =
1042 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1043 final int preferredLaunchDisplayId =
1044 (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
1046 if (reusedActivity != null) {
1047 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1048 // still needs to be a lock task mode violation since the task gets cleared out and
1049 // the device would otherwise leave the locked task.
1050 if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
1051 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1052 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1053 mSupervisor.showLockTaskToast();
1054 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1055 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1058 if (mStartActivity.getTask() == null) {
1059 mStartActivity.setTask(reusedActivity.getTask());
1061 if (reusedActivity.getTask().intent == null) {
1062 // This task was started because of movement of the activity based on affinity...
1063 // Now that we are actually launching it, we can assign the base intent.
1064 reusedActivity.getTask().setIntent(mStartActivity);
1067 // This code path leads to delivering a new intent, we want to make sure we schedule it
1068 // as the first operation, in case the activity will be resumed as a result of later
1070 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1071 || isDocumentLaunchesIntoExisting(mLaunchFlags)
1072 || mLaunchSingleInstance || mLaunchSingleTask) {
1073 final TaskRecord task = reusedActivity.getTask();
1075 // In this situation we want to remove all activities from the task up to the one
1076 // being started. In most cases this means we are resetting the task to its initial
1078 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1081 // The above code can remove {@code reusedActivity} from the task, leading to the
1082 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1083 // task reference is needed in the call below to
1084 // {@link setTargetStackAndMoveToFrontIfNeeded}.
1085 if (reusedActivity.getTask() == null) {
1086 reusedActivity.setTask(task);
1090 if (top.frontOfTask) {
1091 // Activity aliases may mean we use different intents for the top activity,
1092 // so make sure the task now has the identity of the new intent.
1093 top.getTask().setIntent(mStartActivity);
1095 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
1096 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1097 mStartActivity.launchedFromPackage);
1101 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1103 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
1105 final ActivityRecord outResult =
1106 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1108 // When there is a reused activity and the current result is a trampoline activity,
1109 // set the reused activity as the result.
1110 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1111 outActivity[0] = reusedActivity;
1114 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1115 // We don't need to start a new activity, and the client said not to do anything
1116 // if that is the case, so this is it! And for paranoia, make sure we have
1117 // correctly resumed the top activity.
1118 resumeTargetStackIfNeeded();
1119 return START_RETURN_INTENT_TO_CALLER;
1121 setTaskFromIntentActivity(reusedActivity);
1123 if (!mAddingToTask && mReuseTask == null) {
1124 // We didn't do anything... but it was needed (a.k.a., client don't use that
1125 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1126 resumeTargetStackIfNeeded();
1127 if (outActivity != null && outActivity.length > 0) {
1128 outActivity[0] = reusedActivity;
1130 return START_TASK_TO_FRONT;
1134 if (mStartActivity.packageName == null) {
1135 final ActivityStack sourceStack = mStartActivity.resultTo != null
1136 ? mStartActivity.resultTo.getStack() : null;
1137 if (sourceStack != null) {
1138 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1139 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1142 ActivityOptions.abort(mOptions);
1143 return START_CLASS_NOT_FOUND;
1146 // If the activity being launched is the same as the one currently at the top, then
1147 // we need to check if it should only be launched once.
1148 final ActivityStack topStack = mSupervisor.mFocusedStack;
1149 final ActivityRecord topFocused = topStack.topActivity();
1150 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1151 final boolean dontStart = top != null && mStartActivity.resultTo == null
1152 && top.realActivity.equals(mStartActivity.realActivity)
1153 && top.userId == mStartActivity.userId
1154 && top.app != null && top.app.thread != null
1155 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1156 || mLaunchSingleTop || mLaunchSingleTask);
1158 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
1159 // For paranoia, make sure we have correctly resumed the top activity.
1160 topStack.mLastPausedActivity = null;
1162 mSupervisor.resumeFocusedStackTopActivityLocked();
1164 ActivityOptions.abort(mOptions);
1165 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1166 // We don't need to start a new activity, and the client said not to do
1167 // anything if that is the case, so this is it!
1168 return START_RETURN_INTENT_TO_CALLER;
1170 top.deliverNewIntentLocked(
1171 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1173 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1174 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1175 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
1176 preferredLaunchDisplayId, topStack.mStackId);
1178 return START_DELIVERED_TO_TOP;
1181 boolean newTask = false;
1182 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1183 ? mSourceRecord.getTask() : null;
1185 // Should this be considered a new task?
1186 int result = START_SUCCESS;
1187 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1188 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1190 result = setTaskFromReuseOrCreateNewTask(
1191 taskToAffiliate, preferredLaunchStackId, topStack);
1192 } else if (mSourceRecord != null) {
1193 result = setTaskFromSourceRecord();
1194 } else if (mInTask != null) {
1195 result = setTaskFromInTask();
1197 // This not being started from an existing activity, and not part of a new task...
1198 // just put it in the top task, though these days this case should never happen.
1199 setTaskToCurrentTopOrCreateNewTask();
1201 if (result != START_SUCCESS) {
1205 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1206 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1207 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1208 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
1209 if (mSourceRecord != null) {
1210 mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
1213 EventLog.writeEvent(
1214 EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1215 mStartActivity.getTask().taskId);
1217 ActivityStack.logStartActivity(
1218 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
1219 mTargetStack.mLastPausedActivity = null;
1221 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1223 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1226 final ActivityRecord topTaskActivity =
1227 mStartActivity.getTask().topRunningActivityLocked();
1228 if (!mTargetStack.isFocusable()
1229 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1230 && mStartActivity != topTaskActivity)) {
1231 // If the activity is not focusable, we can't resume it, but still would like to
1232 // make sure it becomes visible as it starts (this will also trigger entry
1233 // animation). An example of this are PIP activities.
1234 // Also, we don't want to resume activities in a task that currently has an overlay
1235 // as the starting activity just needs to be in the visible paused state until the
1237 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1238 // Go ahead and tell window manager to execute app transition for this activity
1239 // since the app transition will not be triggered through the resume channel.
1240 mWindowManager.executeAppTransition();
1242 // If the target stack was not previously focusable (previous top running activity
1243 // on that stack was not visible) then any prior calls to move the stack to the
1244 // will not update the focused stack. If starting the new activity now allows the
1245 // task stack to be focusable, then ensure that we now update the focused stack
1247 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1248 mTargetStack.moveToFront("startActivityUnchecked");
1250 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1254 mTargetStack.addRecentActivityLocked(mStartActivity);
1256 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1258 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
1259 preferredLaunchDisplayId, mTargetStack.mStackId);
1261 return START_SUCCESS;
1264 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1265 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1266 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1272 mCallingUid = r.launchedFromUid;
1273 mSourceRecord = sourceRecord;
1274 mVoiceSession = voiceSession;
1275 mVoiceInteractor = voiceInteractor;
1277 mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
1279 mLaunchBounds = getOverrideBounds(r, options, inTask);
1281 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1282 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1283 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1284 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1285 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1286 mLaunchTaskBehind = r.mLaunchTaskBehind
1287 && !mLaunchSingleTask && !mLaunchSingleInstance
1288 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1290 sendNewTaskResultRequestIfNeeded();
1292 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1293 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1296 // If we are actually going to launch in to a new task, there are some cases where
1297 // we further want to do multiple task.
1298 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1299 if (mLaunchTaskBehind
1300 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1301 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1305 // We'll invoke onUserLeaving before onPause only if the launching
1306 // activity did not explicitly state that this is an automated launch.
1307 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1308 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1309 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1311 // If the caller has asked not to resume at this point, we make note
1312 // of this in the record so that we can skip it when trying to find
1313 // the top running activity.
1314 mDoResume = doResume;
1315 if (!doResume || !r.okToShowLocked()) {
1316 r.delayedResume = true;
1320 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1321 && mOptions.getTaskOverlay()) {
1322 r.mTaskOverlay = true;
1323 if (!mOptions.canTaskOverlayResume()) {
1324 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1325 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1326 if (top != null && top.state != RESUMED) {
1328 // The caller specifies that we'd like to be avoided to be moved to the front,
1331 mAvoidMoveToFront = true;
1336 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1339 // In some flows in to this function, we retrieve the task record and hold on to it
1340 // without a lock before calling back in to here... so the task at this point may
1341 // not actually be in recents. Check for that, and if it isn't in recents just
1342 // consider it invalid.
1343 if (inTask != null && !inTask.inRecents) {
1344 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1348 mStartFlags = startFlags;
1349 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1350 // is the same as the one making the call... or, as a special case, if we do not know
1351 // the caller then we count the current top activity as the caller.
1352 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1353 ActivityRecord checkedCaller = sourceRecord;
1354 if (checkedCaller == null) {
1355 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1358 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1359 // Caller is not the same as launcher, so always needed.
1360 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1364 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1367 private void sendNewTaskResultRequestIfNeeded() {
1368 final ActivityStack sourceStack = mStartActivity.resultTo != null
1369 ? mStartActivity.resultTo.getStack() : null;
1370 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1371 // For whatever reason this activity is being launched into a new task...
1372 // yet the caller has requested a result back. Well, that is pretty messed up,
1373 // so instead immediately send back a cancel and let the new task continue launched
1374 // as normal without a dependency on its originator.
1375 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1376 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1377 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1379 mStartActivity.resultTo = null;
1383 private void computeLaunchingTaskFlags() {
1384 // If the caller is not coming from another activity, but has given us an explicit task into
1385 // which they would like us to launch the new activity, then let's see about doing that.
1386 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
1387 final Intent baseIntent = mInTask.getBaseIntent();
1388 final ActivityRecord root = mInTask.getRootActivity();
1389 if (baseIntent == null) {
1390 ActivityOptions.abort(mOptions);
1391 throw new IllegalArgumentException("Launching into task without base intent: "
1395 // If this task is empty, then we are adding the first activity -- it
1396 // determines the root, and must be launching as a NEW_TASK.
1397 if (mLaunchSingleInstance || mLaunchSingleTask) {
1398 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1399 ActivityOptions.abort(mOptions);
1400 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1401 + mStartActivity + " into different task " + mInTask);
1404 ActivityOptions.abort(mOptions);
1405 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1406 + " has root " + root + " but target is singleInstance/Task");
1410 // If task is empty, then adopt the interesting intent launch flags in to the
1411 // activity being started.
1413 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1414 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1415 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1416 | (baseIntent.getFlags() & flagsOfInterest);
1417 mIntent.setFlags(mLaunchFlags);
1418 mInTask.setIntent(mStartActivity);
1419 mAddingToTask = true;
1421 // If the task is not empty and the caller is asking to start it as the root of
1422 // a new task, then we don't actually want to start this on the task. We will
1423 // bring the task to the front, and possibly give it a new intent.
1424 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1425 mAddingToTask = false;
1428 mAddingToTask = true;
1431 mReuseTask = mInTask;
1434 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1435 // when in freeform workspace.
1436 // Also put noDisplay activities in the source task. These by itself can be placed
1437 // in any task/stack, however it could launch other activities like ResolverActivity,
1438 // and we want those to stay in the original task.
1439 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1440 && mSourceRecord.isFreeform()) {
1441 mAddingToTask = true;
1445 if (mInTask == null) {
1446 if (mSourceRecord == null) {
1447 // This activity is not being started from another... in this
1448 // case we -always- start a new task.
1449 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1450 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1451 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1452 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1454 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1455 // The original activity who is starting us is running as a single
1456 // instance... this new activity it is starting must go on its
1458 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1459 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1460 // The activity being started is a single instance... it always
1461 // gets launched into its own task.
1462 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1467 private void computeSourceStack() {
1468 if (mSourceRecord == null) {
1469 mSourceStack = null;
1472 if (!mSourceRecord.finishing) {
1473 mSourceStack = mSourceRecord.getStack();
1477 // If the source is finishing, we can't further count it as our source. This is because the
1478 // task it is associated with may now be empty and on its way out, so we don't want to
1479 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1480 // a task for it. But save the task information so it can be used when creating the new task.
1481 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1482 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1483 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1484 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1485 mNewTaskInfo = mSourceRecord.info;
1487 // It is not guaranteed that the source record will have a task associated with it. For,
1488 // example, if this method is being called for processing a pending activity launch, it
1489 // is possible that the activity has been removed from the task after the launch was
1491 final TaskRecord sourceTask = mSourceRecord.getTask();
1492 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
1494 mSourceRecord = null;
1495 mSourceStack = null;
1499 * Decide whether the new activity should be inserted into an existing task. Returns null
1500 * if not or an ActivityRecord with the task into which the new activity should be added.
1502 private ActivityRecord getReusableIntentActivity() {
1503 // We may want to try to place the new activity in to an existing task. We always
1504 // do this if the target activity is singleTask or singleInstance; we will also do
1505 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1506 // us to still place it in a new task: multi task, always doc mode, or being asked to
1507 // launch this as a new task behind the current one.
1508 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1509 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1510 || mLaunchSingleInstance || mLaunchSingleTask;
1511 // If bring to front is requested, and no result is requested and we have not been given
1512 // an explicit task to launch in to, and we can find a task that was started with this
1513 // same component, then instead of launching bring that one to the front.
1514 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1515 ActivityRecord intentActivity = null;
1516 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1517 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1518 intentActivity = task != null ? task.getTopActivity() : null;
1519 } else if (putIntoExistingTask) {
1520 if (mLaunchSingleInstance) {
1521 // There can be one and only one instance of single instance activity in the
1522 // history, and it is always in its own unique task, so we do a special search.
1523 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
1524 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1525 // For the launch adjacent case we only want to put the activity in an existing
1526 // task if the activity already exists in the history.
1527 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1528 !mLaunchSingleTask);
1530 // Otherwise find the best task to put the activity in.
1531 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
1534 return intentActivity;
1538 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1539 * then return the Vr mode's virtual display ID. If not, if the source activity has
1540 * a explicit display ID set, use that to launch the activity.
1542 private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
1543 // Check if the Activity is a VR activity. If so, the activity should be launched in
1545 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1546 return DEFAULT_DISPLAY;
1549 // Get the virtual display id from ActivityManagerService.
1550 int displayId = mService.mVr2dDisplayId;
1551 if (displayId != INVALID_DISPLAY) {
1553 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1555 mUsingVr2dDisplay = true;
1559 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1560 // If the activity has a displayId set explicitly, launch it on the same displayId.
1561 if (displayId != INVALID_DISPLAY) {
1564 return DEFAULT_DISPLAY;
1568 * Figure out which task and activity to bring to front when we have found an existing matching
1569 * activity record in history. May also clear the task if needed.
1570 * @param intentActivity Existing matching activity.
1571 * @return {@link ActivityRecord} brought to front.
1573 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1574 mTargetStack = intentActivity.getStack();
1575 mTargetStack.mLastPausedActivity = null;
1576 // If the target task is not in the front, then we need to bring it to the front...
1577 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1578 // the same behavior as if a new instance was being started, which means not bringing it
1579 // to the front if the caller is not itself in the front.
1580 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1581 ActivityRecord curTop = (focusStack == null)
1582 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1584 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1586 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
1587 && !mAvoidMoveToFront) {
1588 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1589 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1590 mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
1591 // We really do want to push this one into the user's face, right now.
1592 if (mLaunchTaskBehind && mSourceRecord != null) {
1593 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
1595 mMovedOtherTask = true;
1597 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1598 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1599 // So no point resuming any of the activities here, it just wastes one extra
1600 // resuming, plus enter AND exit transitions.
1601 // Here we only want to bring the target stack forward. Transition will be applied
1602 // to the new activity that's started after the old ones are gone.
1603 final boolean willClearTask =
1604 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1605 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1606 if (!willClearTask) {
1607 final ActivityStack launchStack = getLaunchStack(
1608 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1609 final TaskRecord intentTask = intentActivity.getTask();
1610 if (launchStack == null || launchStack == mTargetStack) {
1611 // We only want to move to the front, if we aren't going to launch on a
1612 // different stack. If we launch on a different stack, we will put the
1613 // task on top there.
1614 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1615 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1616 mMovedToFront = true;
1617 } else if (launchStack.mStackId == DOCKED_STACK_ID
1618 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1619 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1620 // If we want to launch adjacent and mTargetStack is not the computed
1621 // launch stack - move task to top of computed stack.
1622 intentTask.reparent(launchStack.mStackId, ON_TOP,
1623 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1626 // TODO: This should be reevaluated in MW v2.
1627 // We choose to move task to front instead of launching it adjacent
1628 // when specific stack was requested explicitly and it appeared to be
1629 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1630 mTargetStack.moveTaskToFrontLocked(intentTask,
1631 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
1632 "bringToFrontInsteadOfAdjacentLaunch");
1634 mMovedToFront = true;
1635 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1636 // Target and computed stacks are on different displays and we've
1637 // found a matching task - move the existing instance to that display and
1638 // move it to front.
1639 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
1640 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1641 "reparentToDisplay");
1642 mMovedToFront = true;
1646 // We are moving a task to the front, use starting window to hide initial drawn
1648 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1649 true /* taskSwitch */);
1651 updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
1654 if (!mMovedToFront && mDoResume) {
1655 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1656 + " from " + intentActivity);
1657 mTargetStack.moveToFront("intentActivityFound");
1660 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
1661 DEFAULT_DISPLAY, mTargetStack.mStackId);
1663 // If the caller has requested that the target task be reset, then do so.
1664 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1665 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1667 return intentActivity;
1670 private void updateTaskReturnToType(
1671 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1672 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1673 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1674 // Caller wants to appear on home activity.
1675 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1677 } else if (focusedStack == null || focusedStack.isHomeStack()) {
1678 // Task will be launched over the home stack, so return home.
1679 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1681 } else if (focusedStack != null && focusedStack != task.getStack() &&
1682 focusedStack.isAssistantStack()) {
1683 // Task was launched over the assistant stack, so return there
1684 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1688 // Else we are coming from an application stack so return to an application.
1689 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1692 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1693 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1694 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1695 // The caller has requested to completely replace any existing task with its new
1696 // activity. Well that should not be too hard...
1697 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1698 // removed from calling performClearTaskLocked (For example, if it is being brought out
1699 // of history or if it is finished immediately), thus disassociating the task. Also note
1700 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1701 // launching another activity.
1702 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1703 // already launching one.
1704 final TaskRecord task = intentActivity.getTask();
1705 task.performClearTaskLocked();
1707 mReuseTask.setIntent(mStartActivity);
1709 // When we clear the task - focus will be adjusted, which will bring another task
1710 // to top before we launch the activity we need. This will temporary swap their
1711 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1712 mMovedOtherTask = true;
1713 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1714 || mLaunchSingleInstance || mLaunchSingleTask) {
1715 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
1718 // A special case: we need to start the activity because it is not currently
1719 // running, and the caller has asked to clear the current task to have this
1720 // activity at the top.
1721 mAddingToTask = true;
1723 // We are no longer placing the activity in the task we previously thought we were.
1724 mStartActivity.setTask(null);
1725 // Now pretend like this activity is being started by the top of its task, so it
1726 // is put in the right place.
1727 mSourceRecord = intentActivity;
1728 final TaskRecord task = mSourceRecord.getTask();
1729 if (task != null && task.getStack() == null) {
1730 // Target stack got cleared when we all activities were removed above.
1731 // Go ahead and reset it.
1732 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1733 null /* bounds */, mLaunchFlags, mOptions);
1734 mTargetStack.addTask(task,
1735 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1738 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
1739 // In this case the top activity on the task is the same as the one being launched,
1740 // so we take that as a request to bring the task to the foreground. If the top
1741 // activity in the task is the root activity, deliver this new intent to it if it
1743 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1744 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1745 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1746 intentActivity.getTask());
1747 if (intentActivity.frontOfTask) {
1748 intentActivity.getTask().setIntent(mStartActivity);
1750 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1751 mStartActivity.launchedFromPackage);
1752 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
1753 // In this case we are launching the root activity of the task, but with a
1754 // different intent. We should start a new instance on top.
1755 mAddingToTask = true;
1756 mSourceRecord = intentActivity;
1758 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1759 // In this case an activity is being launched in to an existing task, without
1760 // resetting that task. This is typically the situation of launching an activity
1761 // from a notification or shortcut. We want to place the new activity on top of the
1763 mAddingToTask = true;
1764 mSourceRecord = intentActivity;
1765 } else if (!intentActivity.getTask().rootWasReset) {
1766 // In this case we are launching into an existing task that has not yet been started
1767 // from its front door. The current task has been brought to the front. Ideally,
1768 // we'd probably like to place this new task at the bottom of its stack, but that's
1769 // a little hard to do with the current organization of the code so for now we'll
1771 intentActivity.getTask().setIntent(mStartActivity);
1775 private void resumeTargetStackIfNeeded() {
1777 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1779 ActivityOptions.abort(mOptions);
1781 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1784 private int setTaskFromReuseOrCreateNewTask(
1785 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1786 mTargetStack = computeStackFocus(
1787 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1789 // Do no move the target stack to front yet, as we might bail if
1790 // isLockTaskModeViolation fails below.
1792 if (mReuseTask == null) {
1793 final TaskRecord task = mTargetStack.createTaskRecord(
1794 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1795 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1796 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1797 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
1798 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
1799 if (mLaunchBounds != null) {
1800 final int stackId = mTargetStack.mStackId;
1801 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1802 mService.resizeStack(
1803 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1805 mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
1808 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1809 + " in new task " + mStartActivity.getTask());
1811 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1814 if (taskToAffiliate != null) {
1815 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
1818 if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
1819 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1820 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1823 if (!mMovedOtherTask) {
1824 // If stack id is specified in activity options, usually it means that activity is
1825 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1826 // that case we check the target stack.
1827 updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
1828 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1831 mTargetStack.moveToFront("reuseOrNewTask");
1833 return START_SUCCESS;
1836 private int setTaskFromSourceRecord() {
1837 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
1838 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1839 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1842 final TaskRecord sourceTask = mSourceRecord.getTask();
1843 final ActivityStack sourceStack = mSourceRecord.getStack();
1844 // We only want to allow changing stack if the target task is not the top one,
1845 // otherwise we would move the launching task to the other side, rather than show
1846 // two side by side.
1847 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
1848 if (moveStackAllowed) {
1849 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
1853 if (mTargetStack == null) {
1854 mTargetStack = sourceStack;
1855 } else if (mTargetStack != sourceStack) {
1856 sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1857 !ANIMATE, DEFER_RESUME, "launchToSide");
1860 final TaskRecord topTask = mTargetStack.topTask();
1861 if (topTask != sourceTask && !mAvoidMoveToFront) {
1862 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1863 mStartActivity.appTimeTracker, "sourceTaskToFront");
1864 } else if (mDoResume) {
1865 mTargetStack.moveToFront("sourceStackToFront");
1868 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1869 // In this case, we are adding the activity to an existing task, but the caller has
1870 // asked to clear that task if the activity is already running.
1871 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1872 mKeepCurTransition = true;
1874 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
1875 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1876 // For paranoia, make sure we have correctly resumed the top activity.
1877 mTargetStack.mLastPausedActivity = null;
1879 mSupervisor.resumeFocusedStackTopActivityLocked();
1881 ActivityOptions.abort(mOptions);
1882 return START_DELIVERED_TO_TOP;
1884 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1885 // In this case, we are launching an activity in our own task that may already be
1886 // running somewhere in the history, and we want to shuffle it to the front of the
1888 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1890 final TaskRecord task = top.getTask();
1891 task.moveActivityToFrontLocked(top);
1892 top.updateOptionsLocked(mOptions);
1893 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1894 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1895 mTargetStack.mLastPausedActivity = null;
1897 mSupervisor.resumeFocusedStackTopActivityLocked();
1899 return START_DELIVERED_TO_TOP;
1903 // An existing activity is starting this new activity, so we want to keep the new one in
1904 // the same task as the one that is starting it.
1905 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
1906 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1907 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
1908 return START_SUCCESS;
1911 private int setTaskFromInTask() {
1912 // The caller is asking that the new activity be started in an explicit
1913 // task it has provided to us.
1914 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1915 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1916 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1919 mTargetStack = mInTask.getStack();
1921 // Check whether we should actually launch the new activity in to the task,
1922 // or just reuse the current activity on top.
1923 ActivityRecord top = mInTask.getTopActivity();
1924 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1925 && top.userId == mStartActivity.userId) {
1926 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1927 || mLaunchSingleTop || mLaunchSingleTask) {
1928 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1929 mStartActivity.appTimeTracker, "inTaskToFront");
1930 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
1931 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1932 // We don't need to start a new activity, and the client said not to do
1933 // anything if that is the case, so this is it!
1934 return START_RETURN_INTENT_TO_CALLER;
1936 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1937 mStartActivity.launchedFromPackage);
1938 return START_DELIVERED_TO_TOP;
1942 if (!mAddingToTask) {
1943 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1944 mStartActivity.appTimeTracker, "inTaskToFront");
1945 // We don't actually want to have this activity added to the task, so just
1946 // stop here but still tell the caller that we consumed the intent.
1947 ActivityOptions.abort(mOptions);
1948 return START_TASK_TO_FRONT;
1951 if (mLaunchBounds != null) {
1952 mInTask.updateOverrideConfiguration(mLaunchBounds);
1953 int stackId = mInTask.getLaunchStackId();
1954 if (stackId != mInTask.getStackId()) {
1955 mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1956 DEFER_RESUME, "inTaskToFront");
1957 stackId = mInTask.getStackId();
1958 mTargetStack = mInTask.getStack();
1960 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1961 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1965 mTargetStack.moveTaskToFrontLocked(
1966 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1968 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1969 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1970 + " in explicit task " + mStartActivity.getTask());
1972 return START_SUCCESS;
1975 private void setTaskToCurrentTopOrCreateNewTask() {
1976 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1979 mTargetStack.moveToFront("addingToTopTask");
1981 final ActivityRecord prev = mTargetStack.topActivity();
1982 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
1983 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1984 mIntent, null, null, true, mStartActivity.mActivityType);
1985 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1986 mTargetStack.positionChildWindowContainerAtTop(task);
1987 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1988 + " in new guessed " + mStartActivity.getTask());
1991 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
1992 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
1993 parent.addActivityToTop(mStartActivity);
1995 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1999 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2000 boolean launchSingleTask, int launchFlags) {
2001 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2002 (launchSingleInstance || launchSingleTask)) {
2003 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2004 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2005 "\"singleInstance\" or \"singleTask\"");
2007 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2009 switch (r.info.documentLaunchMode) {
2010 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2012 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2013 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2015 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2016 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2018 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2019 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2026 final void doPendingActivityLaunchesLocked(boolean doResume) {
2027 while (!mPendingActivityLaunches.isEmpty()) {
2028 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
2029 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
2031 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
2032 null, null /*outRecords*/);
2033 } catch (Exception e) {
2034 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
2035 pal.sendErrorResult(e.getMessage());
2040 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
2041 int launchFlags, ActivityOptions aOptions) {
2042 final TaskRecord task = r.getTask();
2043 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
2044 if (stack != null) {
2048 final ActivityStack currentStack = task != null ? task.getStack() : null;
2049 if (currentStack != null) {
2050 if (mSupervisor.mFocusedStack != currentStack) {
2051 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2052 "computeStackFocus: Setting " + "focused stack to r=" + r
2055 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2056 "computeStackFocus: Focused stack already="
2057 + mSupervisor.mFocusedStack);
2059 return currentStack;
2062 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
2063 if (container != null) {
2064 // The first time put it on the desired stack, after this put on task stack.
2065 r.mInitialActivityContainer = null;
2066 return container.mStack;
2069 if (canLaunchIntoFocusedStack(r, newTask)) {
2070 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2071 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2072 return mSupervisor.mFocusedStack;
2075 if (mSourceDisplayId != DEFAULT_DISPLAY) {
2076 // Try to put the activity in a stack on a secondary display.
2077 stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2078 if (stack == null) {
2079 // If source display is not suitable - look for topmost valid stack in the system.
2080 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2081 "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
2082 + ", looking on all displays.");
2083 stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
2086 if (stack == null) {
2087 // We first try to put the task in the first dynamic stack on home display.
2088 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2089 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2090 stack = homeDisplayStacks.get(stackNdx);
2091 if (isDynamicStack(stack.mStackId)) {
2092 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2093 "computeStackFocus: Setting focused stack=" + stack);
2097 // If there is no suitable dynamic stack then we figure out which static stack to use.
2098 final int stackId = task != null ? task.getLaunchStackId() :
2099 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2100 FULLSCREEN_WORKSPACE_STACK_ID;
2101 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
2103 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2104 + r + " stackId=" + stack.mStackId);
2108 /** Check if provided activity record can launch in currently focused stack. */
2109 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
2110 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2111 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2112 final boolean canUseFocusedStack;
2113 switch (focusedStackId) {
2114 case FULLSCREEN_WORKSPACE_STACK_ID:
2115 // The fullscreen stack can contain any task regardless of if the task is resizeable
2116 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
2117 canUseFocusedStack = true;
2119 case ASSISTANT_STACK_ID:
2120 canUseFocusedStack = r.isAssistantActivity();
2122 case DOCKED_STACK_ID:
2123 // Any activity which supports split screen can go in the docked stack.
2124 canUseFocusedStack = r.supportsSplitScreen();
2126 case FREEFORM_WORKSPACE_STACK_ID:
2127 // Any activity which supports freeform can go in the freeform stack.
2128 canUseFocusedStack = r.supportsFreeform();
2131 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2133 // TODO: Check ActivityView after fixing b/35349678.
2134 canUseFocusedStack = isDynamicStack(focusedStackId)
2135 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2138 return canUseFocusedStack
2139 && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks())
2140 // We strongly prefer to launch activities on the same display as their source.
2141 && (mSourceDisplayId == focusedStack.mDisplayId);
2144 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
2145 ActivityOptions aOptions) {
2146 // We are reusing a task, keep the stack!
2147 if (mReuseTask != null) {
2148 return mReuseTask.getStack();
2151 // If the activity is of a specific type, return the associated stack, creating it if
2153 if (r.isHomeActivity()) {
2154 return mSupervisor.mHomeStack;
2156 if (r.isRecentsActivity()) {
2157 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2159 if (r.isAssistantActivity()) {
2160 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2163 final int launchDisplayId =
2164 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2166 final int launchStackId =
2167 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2169 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2170 throw new IllegalArgumentException(
2171 "Stack and display id can't be set at the same time.");
2174 if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
2175 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
2177 if (launchStackId == DOCKED_STACK_ID) {
2178 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2179 // for this activity, so we put the activity in the fullscreen stack.
2180 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2182 if (launchDisplayId != INVALID_DISPLAY) {
2183 // Stack id has higher priority than display id.
2184 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2187 // If we are using Vr2d display, find the virtual display stack.
2188 if (mUsingVr2dDisplay) {
2189 ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2191 Slog.v(TAG, "Launch stack for app: " + r.toString() +
2192 ", on virtual display stack:" + as.toString());
2197 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2198 || mSourceDisplayId != DEFAULT_DISPLAY) {
2201 // Otherwise handle adjacent launch.
2203 // The parent activity doesn't want to launch the activity on top of itself, but
2204 // instead tries to put it onto other side in side-by-side mode.
2205 final ActivityStack parentStack = task != null ? task.getStack()
2206 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2207 : mSupervisor.mFocusedStack;
2209 if (parentStack != mSupervisor.mFocusedStack) {
2210 // If task's parent stack is not focused - use it during adjacent launch.
2213 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2214 // If task is already on top of focused stack - use it. We don't want to move the
2215 // existing focused task to adjacent stack, just deliver new intent in this case.
2216 return mSupervisor.mFocusedStack;
2219 if (parentStack != null && parentStack.isDockedStack()) {
2220 // If parent was in docked stack, the natural place to launch another activity
2221 // will be fullscreen, so it can appear alongside the docked window.
2222 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2225 // If the parent is not in the docked stack, we check if there is docked window
2226 // and if yes, we will launch into that stack. If not, we just put the new
2227 // activity into parent's stack, because we can't find a better place.
2228 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2229 if (dockedStack != null
2230 && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
2231 // There is a docked stack, but it isn't visible, so we can't launch into that.
2240 boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
2242 case INVALID_STACK_ID:
2245 case FULLSCREEN_WORKSPACE_STACK_ID:
2247 case FREEFORM_WORKSPACE_STACK_ID:
2248 return r.supportsFreeform();
2249 case DOCKED_STACK_ID:
2250 return r.supportsSplitScreen();
2251 case PINNED_STACK_ID:
2252 return r.supportsPictureInPicture();
2253 case RECENTS_STACK_ID:
2254 return r.isRecentsActivity();
2255 case ASSISTANT_STACK_ID:
2256 return r.isAssistantActivity();
2258 // TODO: Check ActivityView after fixing b/35349678.
2259 if (StackId.isDynamicStack(stackId)) {
2260 return r.canBeLaunchedOnDisplay(displayId);
2262 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2267 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2268 Rect newBounds = null;
2269 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2270 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2271 options, options.getLaunchStackId())) {
2272 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2278 void setWindowManager(WindowManagerService wm) {
2279 mWindowManager = wm;
2282 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2283 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2284 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2285 if (pal.stack == stack) {
2286 mPendingActivityLaunches.remove(palNdx);
2291 static boolean isDocumentLaunchesIntoExisting(int flags) {
2292 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2293 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2296 boolean clearPendingActivityLaunchesLocked(String packageName) {
2297 boolean didSomething = false;
2299 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2300 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2301 ActivityRecord r = pal.r;
2302 if (r != null && r.packageName.equals(packageName)) {
2303 mPendingActivityLaunches.remove(palNdx);
2304 didSomething = true;
2307 return didSomething;
2310 void dump(PrintWriter pw, String prefix) {
2311 pw.println(prefix + "ActivityStarter:");
2312 prefix = prefix + " ";
2314 pw.println(prefix + "mCurrentUser=" + mSupervisor.mCurrentUser);
2315 pw.println(prefix + "mLastStartReason=" + mLastStartReason);
2316 pw.println(prefix + "mLastStartActivityTimeMs="
2317 + DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2318 pw.println(prefix + "mLastStartActivityResult=" + mLastStartActivityResult);
2319 ActivityRecord r = mLastStartActivityRecord[0];
2321 pw.println(prefix + "mLastStartActivityRecord:");
2322 r.dump(pw, prefix + " ");
2324 pw.println(prefix + "mLastHomeActivityStartResult=" + mLastHomeActivityStartResult);
2325 r = mLastHomeActivityStartRecord[0];
2327 pw.println(prefix + "mLastHomeActivityStartRecord:");
2328 r.dump(pw, prefix + " ");
2330 if (mStartActivity != null) {
2331 pw.println(prefix + "mStartActivity:");
2332 mStartActivity.dump(pw, prefix + " ");
2334 if (mIntent != null) {
2335 pw.println(prefix + "mIntent=" + mIntent);
2337 if (mOptions != null) {
2338 pw.println(prefix + "mOptions=" + mOptions);
2340 pw.println(prefix + "mLaunchSingleTop=" + mLaunchSingleTop
2341 + " mLaunchSingleInstance=" + mLaunchSingleInstance
2342 + " mLaunchSingleTask=" + mLaunchSingleTask
2343 + " mLaunchFlags=0x" + Integer.toHexString(mLaunchFlags)
2344 + " mDoResume=" + mDoResume + " mAddingToTask=" + mAddingToTask);