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.IApplicationThread;
94 import android.app.PendingIntent;
95 import android.app.ProfilerInfo;
96 import android.app.WaitResult;
97 import android.content.IIntentSender;
98 import android.content.Intent;
99 import android.content.IntentSender;
100 import android.content.pm.ActivityInfo;
101 import android.content.pm.ApplicationInfo;
102 import android.content.pm.AuxiliaryResolveInfo;
103 import android.content.pm.PackageManager;
104 import android.content.pm.ResolveInfo;
105 import android.content.pm.UserInfo;
106 import android.content.res.Configuration;
107 import android.graphics.Rect;
108 import android.hardware.power.V1_0.PowerHint;
109 import android.os.Binder;
110 import android.os.Bundle;
111 import android.os.IBinder;
112 import android.os.RemoteException;
113 import android.os.SystemClock;
114 import android.os.UserHandle;
115 import android.os.UserManager;
116 import android.service.voice.IVoiceInteractionSession;
117 import android.text.TextUtils;
118 import android.util.EventLog;
119 import android.util.Slog;
121 import com.android.internal.app.HeavyWeightSwitcherActivity;
122 import com.android.internal.app.IVoiceInteractor;
123 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
124 import com.android.server.pm.InstantAppResolver;
125 import com.android.server.wm.WindowManagerService;
127 import java.io.PrintWriter;
128 import java.text.DateFormat;
129 import java.util.ArrayList;
130 import java.util.Date;
133 * Controller for interpreting how and then launching activities.
135 * This class collects all the logic for determining how an intent and flags should be turned into
136 * an activity and associated task and stack.
138 class ActivityStarter {
139 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
140 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
141 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
142 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
143 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
145 private final ActivityManagerService mService;
146 private final ActivityStackSupervisor mSupervisor;
147 private ActivityStartInterceptor mInterceptor;
148 private WindowManagerService mWindowManager;
150 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
152 // Share state variable among methods when starting an activity.
153 private ActivityRecord mStartActivity;
154 private Intent mIntent;
155 private int mCallingUid;
156 private ActivityOptions mOptions;
158 private boolean mLaunchSingleTop;
159 private boolean mLaunchSingleInstance;
160 private boolean mLaunchSingleTask;
161 private boolean mLaunchTaskBehind;
162 private int mLaunchFlags;
164 private Rect mLaunchBounds;
166 private ActivityRecord mNotTop;
167 private boolean mDoResume;
168 private int mStartFlags;
169 private ActivityRecord mSourceRecord;
170 private int mSourceDisplayId;
172 private TaskRecord mInTask;
173 private boolean mAddingToTask;
174 private TaskRecord mReuseTask;
176 private ActivityInfo mNewTaskInfo;
177 private Intent mNewTaskIntent;
178 private ActivityStack mSourceStack;
179 private ActivityStack mTargetStack;
180 // Indicates that we moved other task and are going to put something on top soon, so
181 // we don't want to show it redundantly or accidentally change what's shown below.
182 private boolean mMovedOtherTask;
183 private boolean mMovedToFront;
184 private boolean mNoAnimation;
185 private boolean mKeepCurTransition;
186 private boolean mAvoidMoveToFront;
187 private boolean mPowerHintSent;
189 // We must track when we deliver the new intent since multiple code paths invoke
190 // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
191 // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
192 // delivered at most once.
193 private boolean mIntentDelivered;
195 private IVoiceInteractionSession mVoiceSession;
196 private IVoiceInteractor mVoiceInteractor;
198 private boolean mUsingVr2dDisplay;
200 // Last home activity record we attempted to start
201 private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
202 // The result of the last home activity we attempted to start.
203 private int mLastHomeActivityStartResult;
204 // Last activity record we attempted to start
205 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
206 // The result of the last activity we attempted to start.
207 private int mLastStartActivityResult;
208 // Time in milli seconds we attempted to start the last activity.
209 private long mLastStartActivityTimeMs;
210 // The reason we were trying to start the last activity
211 private String mLastStartReason;
213 private void reset() {
214 mStartActivity = null;
219 mLaunchSingleTop = false;
220 mLaunchSingleInstance = false;
221 mLaunchSingleTask = false;
222 mLaunchTaskBehind = false;
225 mLaunchBounds = null;
230 mSourceRecord = null;
231 mSourceDisplayId = INVALID_DISPLAY;
234 mAddingToTask = false;
238 mNewTaskIntent = null;
242 mMovedOtherTask = false;
243 mMovedToFront = false;
244 mNoAnimation = false;
245 mKeepCurTransition = false;
246 mAvoidMoveToFront = false;
248 mVoiceSession = null;
249 mVoiceInteractor = null;
251 mUsingVr2dDisplay = false;
253 mIntentDelivered = false;
256 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
258 mSupervisor = supervisor;
259 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
260 mUsingVr2dDisplay = false;
263 int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
264 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
265 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
266 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
267 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
268 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
269 ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
271 if (TextUtils.isEmpty(reason)) {
272 throw new IllegalArgumentException("Need to specify a reason.");
274 mLastStartReason = reason;
275 mLastStartActivityTimeMs = System.currentTimeMillis();
276 mLastStartActivityRecord[0] = null;
278 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
279 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
280 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
281 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
284 if (outActivity != null) {
285 // mLastStartActivityRecord[0] is set in the call to startActivity above.
286 outActivity[0] = mLastStartActivityRecord[0];
289 // Aborted results are treated as successes externally, but we must track them internally.
290 return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
293 /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
294 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
295 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
296 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
297 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
298 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
299 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
300 ActivityRecord[] outActivity, TaskRecord inTask) {
301 int err = ActivityManager.START_SUCCESS;
302 // Pull the optional Ephemeral Installer-only bundle out of the options early.
303 final Bundle verificationBundle
304 = options != null ? options.popAppVerificationBundle() : null;
306 ProcessRecord callerApp = null;
307 if (caller != null) {
308 callerApp = mService.getRecordForAppLocked(caller);
309 if (callerApp != null) {
310 callingPid = callerApp.pid;
311 callingUid = callerApp.info.uid;
313 Slog.w(TAG, "Unable to find app for caller " + caller
314 + " (pid=" + callingPid + ") when starting: "
315 + intent.toString());
316 err = ActivityManager.START_PERMISSION_DENIED;
320 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
322 if (err == ActivityManager.START_SUCCESS) {
323 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
324 + "} from uid " + callingUid);
327 ActivityRecord sourceRecord = null;
328 ActivityRecord resultRecord = null;
329 if (resultTo != null) {
330 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
331 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
332 "Will send result to " + resultTo + " " + sourceRecord);
333 if (sourceRecord != null) {
334 if (requestCode >= 0 && !sourceRecord.finishing) {
335 resultRecord = sourceRecord;
340 final int launchFlags = intent.getFlags();
342 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
343 // Transfer the result target from the source activity to the new
344 // one being started, including any failures.
345 if (requestCode >= 0) {
346 ActivityOptions.abort(options);
347 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
349 resultRecord = sourceRecord.resultTo;
350 if (resultRecord != null && !resultRecord.isInStackLocked()) {
353 resultWho = sourceRecord.resultWho;
354 requestCode = sourceRecord.requestCode;
355 sourceRecord.resultTo = null;
356 if (resultRecord != null) {
357 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
359 if (sourceRecord.launchedFromUid == callingUid) {
360 // The new activity is being launched from the same uid as the previous
361 // activity in the flow, and asking to forward its result back to the
362 // previous. In this case the activity is serving as a trampoline between
363 // the two, so we also want to update its launchedFromPackage to be the
364 // same as the previous activity. Note that this is safe, since we know
365 // these two packages come from the same uid; the caller could just as
366 // well have supplied that same package name itself. This specifially
367 // deals with the case of an intent picker/chooser being launched in the app
368 // flow to redirect to an activity picked by the user, where we want the final
369 // activity to consider it to have been launched by the previous app activity.
370 callingPackage = sourceRecord.launchedFromPackage;
374 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
375 // We couldn't find a class that can handle the given Intent.
376 // That's the end of that!
377 err = ActivityManager.START_INTENT_NOT_RESOLVED;
380 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
381 // We couldn't find the specific class specified in the Intent.
382 // Also the end of the line.
383 err = ActivityManager.START_CLASS_NOT_FOUND;
386 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
387 && sourceRecord.getTask().voiceSession != null) {
388 // If this activity is being launched as part of a voice session, we need
389 // to ensure that it is safe to do so. If the upcoming activity will also
390 // be part of the voice session, we can only launch it if it has explicitly
391 // said it supports the VOICE category, or it is a part of the calling app.
392 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
393 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
395 intent.addCategory(Intent.CATEGORY_VOICE);
396 if (!AppGlobals.getPackageManager().activitySupportsIntent(
397 intent.getComponent(), intent, resolvedType)) {
399 "Activity being started in current voice task does not support voice: "
401 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
403 } catch (RemoteException e) {
404 Slog.w(TAG, "Failure checking voice capabilities", e);
405 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
410 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
411 // If the caller is starting a new voice session, just make sure the target
412 // is actually allowing it to run this way.
414 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
415 intent, resolvedType)) {
417 "Activity being started in new voice task does not support: "
419 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
421 } catch (RemoteException e) {
422 Slog.w(TAG, "Failure checking voice capabilities", e);
423 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
427 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
429 if (err != START_SUCCESS) {
430 if (resultRecord != null) {
431 resultStack.sendActivityResultLocked(
432 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
434 ActivityOptions.abort(options);
438 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
439 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
440 resultRecord, resultStack, options);
441 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
442 callingPid, resolvedType, aInfo.applicationInfo);
444 if (mService.mController != null) {
446 // The Intent we give to the watcher has the extra data
447 // stripped off, since it can contain private information.
448 Intent watchIntent = intent.cloneFilter();
449 abort |= !mService.mController.activityStarting(watchIntent,
450 aInfo.applicationInfo.packageName);
451 } catch (RemoteException e) {
452 mService.mController = null;
456 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
457 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
459 intent = mInterceptor.mIntent;
460 rInfo = mInterceptor.mRInfo;
461 aInfo = mInterceptor.mAInfo;
462 resolvedType = mInterceptor.mResolvedType;
463 inTask = mInterceptor.mInTask;
464 callingPid = mInterceptor.mCallingPid;
465 callingUid = mInterceptor.mCallingUid;
466 options = mInterceptor.mActivityOptions;
468 if (resultRecord != null) {
469 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
470 RESULT_CANCELED, null);
472 // We pretend to the caller that it was really started, but
473 // they will just get a cancel result.
474 ActivityOptions.abort(options);
475 return START_ABORTED;
478 // If permissions need a review before any of the app components can run, we
479 // launch the review activity and pass a pending intent to start the activity
480 // we are to launching now after the review is completed.
481 if (mService.mPermissionReviewRequired && aInfo != null) {
482 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
483 aInfo.packageName, userId)) {
484 IIntentSender target = mService.getIntentSenderLocked(
485 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
486 callingUid, userId, null, null, 0, new Intent[]{intent},
487 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
488 | PendingIntent.FLAG_ONE_SHOT, null);
490 final int flags = intent.getFlags();
491 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
492 newIntent.setFlags(flags
493 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
494 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
495 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
496 if (resultRecord != null) {
497 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
502 callingUid = realCallingUid;
503 callingPid = realCallingPid;
505 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
506 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
507 null /*profilerInfo*/);
509 if (DEBUG_PERMISSIONS_REVIEW) {
510 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
511 true, false) + "} from uid " + callingUid + " on display "
512 + (mSupervisor.mFocusedStack == null
513 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
518 // If we have an ephemeral app, abort the process of launching the resolved intent.
519 // Instead, launch the ephemeral installer. Once the installer is finished, it
520 // starts either the intent we resolved here [on install error] or the ephemeral
521 // app [on install success].
522 if (rInfo != null && rInfo.auxiliaryInfo != null) {
523 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
524 callingPackage, verificationBundle, resolvedType, userId);
526 callingUid = realCallingUid;
527 callingPid = realCallingPid;
529 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
532 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
533 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
534 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
535 mSupervisor, options, sourceRecord);
536 if (outActivity != null) {
540 if (r.appTimeTracker == null && sourceRecord != null) {
541 // If the caller didn't specify an explicit time tracker, we want to continue
542 // tracking under any it has.
543 r.appTimeTracker = sourceRecord.appTimeTracker;
546 final ActivityStack stack = mSupervisor.mFocusedStack;
547 if (voiceSession == null && (stack.mResumedActivity == null
548 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
549 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
550 realCallingPid, realCallingUid, "Activity start")) {
551 PendingActivityLaunch pal = new PendingActivityLaunch(r,
552 sourceRecord, startFlags, stack, callerApp);
553 mPendingActivityLaunches.add(pal);
554 ActivityOptions.abort(options);
555 return ActivityManager.START_SWITCHES_CANCELED;
559 if (mService.mDidAppSwitch) {
560 // This is the second allowed switch since we stopped switches,
561 // so now just generally allow switches. Use case: user presses
562 // home (switches disabled, switch to home, mDidAppSwitch now true);
563 // user taps a home icon (coming from home so allowed, we hit here
564 // and now allow anyone to switch again).
565 mService.mAppSwitchesAllowedTime = 0;
567 mService.mDidAppSwitch = true;
570 doPendingActivityLaunchesLocked(false);
572 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
573 options, inTask, outActivity);
577 * Creates a launch intent for the given auxiliary resolution data.
579 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
580 Intent originalIntent, String callingPackage, Bundle verificationBundle,
581 String resolvedType, int userId) {
582 if (auxiliaryResponse.needsPhaseTwo) {
583 // request phase two resolution
584 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
585 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
586 verificationBundle, userId);
588 return InstantAppResolver.buildEphemeralInstallerIntent(
589 Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
590 auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
591 resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
592 auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode,
593 auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
596 void postStartActivityProcessing(
597 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
598 ActivityStack targetStack) {
600 if (ActivityManager.isStartResultFatalError(result)) {
604 // We're waiting for an activity launch to finish, but that activity simply
605 // brought another activity to front. Let startActivityMayWait() know about
606 // this, so it waits for the new activity to become visible instead.
607 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
608 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
611 int startedActivityStackId = INVALID_STACK_ID;
612 final ActivityStack currentStack = r.getStack();
613 if (currentStack != null) {
614 startedActivityStackId = currentStack.mStackId;
615 } else if (mTargetStack != null) {
616 startedActivityStackId = targetStack.mStackId;
619 if (startedActivityStackId == DOCKED_STACK_ID) {
620 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
621 final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
622 if (homeStackVisible) {
623 // We launch an activity while being in home stack, which means either launcher or
624 // recents into docked stack. We don't want the launched activity to be alone in a
625 // docked stack, so we want to immediately launch recents too.
626 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
627 mWindowManager.showRecentApps(true /* fromHome */);
632 boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
633 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
634 if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
635 || result == START_DELIVERED_TO_TOP || clearedTask)) {
636 // The activity was already running in the pinned stack so it wasn't started, but either
637 // brought to the front or the new intent was delivered to it since it was already in
638 // front. Notify anyone interested in this piece of information.
639 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
645 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
646 mSupervisor.moveHomeStackTaskToTop(reason);
647 mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
648 null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
649 null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
650 null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
651 null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
652 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
653 false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
654 null /*inTask*/, "startHomeActivity: " + reason);
655 if (mSupervisor.inResumeTopActivity) {
656 // If we are in resume section already, home activity will be initialized, but not
657 // resumed (to avoid recursive resume) and will stay that way until something pokes it
658 // again. We need to schedule another resume.
659 mSupervisor.scheduleResumeTopActivities();
663 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
664 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
665 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
666 FLAG_ACTIVITY_TASK_ON_HOME);
667 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
668 : ActivityOptions.makeBasic());
669 options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
670 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
673 final int startActivityMayWait(IApplicationThread caller, int callingUid,
674 String callingPackage, Intent intent, String resolvedType,
675 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
676 IBinder resultTo, String resultWho, int requestCode, int startFlags,
677 ProfilerInfo profilerInfo, WaitResult outResult,
678 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
679 TaskRecord inTask, String reason) {
680 // Refuse possible leaked file descriptors
681 if (intent != null && intent.hasFileDescriptors()) {
682 throw new IllegalArgumentException("File descriptors passed in Intent");
684 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
685 boolean componentSpecified = intent.getComponent() != null;
687 // Save a copy in case ephemeral needs it
688 final Intent ephemeralIntent = new Intent(intent);
689 // Don't modify the client's object!
690 intent = new Intent(intent);
691 if (componentSpecified
692 && intent.getData() != null
693 && Intent.ACTION_VIEW.equals(intent.getAction())
694 && mService.getPackageManagerInternalLocked()
695 .isInstantAppInstallerComponent(intent.getComponent())) {
696 // intercept intents targeted directly to the ephemeral installer the
697 // ephemeral installer should never be started with a raw URL; instead
698 // adjust the intent so it looks like a "normal" instant app launch
699 intent.setComponent(null /*component*/);
700 componentSpecified = false;
703 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
705 UserInfo userInfo = mSupervisor.getUserInfo(userId);
706 if (userInfo != null && userInfo.isManagedProfile()) {
707 // Special case for managed profiles, if attempting to launch non-cryto aware
708 // app in a locked managed profile from an unlocked parent allow it to resolve
709 // as user will be sent via confirm credentials to unlock the profile.
710 UserManager userManager = UserManager.get(mService.mContext);
711 boolean profileLockedAndParentUnlockingOrUnlocked = false;
712 long token = Binder.clearCallingIdentity();
714 UserInfo parent = userManager.getProfileParent(userId);
715 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
716 && userManager.isUserUnlockingOrUnlocked(parent.id)
717 && !userManager.isUserUnlockingOrUnlocked(userId);
719 Binder.restoreCallingIdentity(token);
721 if (profileLockedAndParentUnlockingOrUnlocked) {
722 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
723 PackageManager.MATCH_DIRECT_BOOT_AWARE
724 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
728 // Collect information about the target of the Intent.
729 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
731 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
732 synchronized (mService) {
733 final int realCallingPid = Binder.getCallingPid();
734 final int realCallingUid = Binder.getCallingUid();
736 if (callingUid >= 0) {
738 } else if (caller == null) {
739 callingPid = realCallingPid;
740 callingUid = realCallingUid;
742 callingPid = callingUid = -1;
745 final ActivityStack stack = mSupervisor.mFocusedStack;
746 stack.mConfigWillChange = globalConfig != null
747 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
748 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
749 "Starting activity when config will change = " + stack.mConfigWillChange);
751 final long origId = Binder.clearCallingIdentity();
754 (aInfo.applicationInfo.privateFlags
755 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
756 // This may be a heavy-weight process! Check to see if we already
757 // have another, different heavy-weight process running.
758 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
759 final ProcessRecord heavy = mService.mHeavyWeightProcess;
760 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
761 || !heavy.processName.equals(aInfo.processName))) {
762 int appCallingUid = callingUid;
763 if (caller != null) {
764 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
765 if (callerApp != null) {
766 appCallingUid = callerApp.info.uid;
768 Slog.w(TAG, "Unable to find app for caller " + caller
769 + " (pid=" + callingPid + ") when starting: "
770 + intent.toString());
771 ActivityOptions.abort(options);
772 return ActivityManager.START_PERMISSION_DENIED;
776 IIntentSender target = mService.getIntentSenderLocked(
777 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
778 appCallingUid, userId, null, null, 0, new Intent[] { intent },
779 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
780 | PendingIntent.FLAG_ONE_SHOT, null);
782 Intent newIntent = new Intent();
783 if (requestCode >= 0) {
784 // Caller is requesting a result.
785 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
787 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
788 new IntentSender(target));
789 if (heavy.activities.size() > 0) {
790 ActivityRecord hist = heavy.activities.get(0);
791 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
793 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
794 hist.getTask().taskId);
796 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
798 newIntent.setFlags(intent.getFlags());
799 newIntent.setClassName("android",
800 HeavyWeightSwitcherActivity.class.getName());
804 callingUid = Binder.getCallingUid();
805 callingPid = Binder.getCallingPid();
806 componentSpecified = true;
807 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
808 aInfo = rInfo != null ? rInfo.activityInfo : null;
810 aInfo = mService.getActivityInfoForUser(aInfo, userId);
816 final ActivityRecord[] outRecord = new ActivityRecord[1];
817 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
818 aInfo, rInfo, voiceSession, voiceInteractor,
819 resultTo, resultWho, requestCode, callingPid,
820 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
821 options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
824 Binder.restoreCallingIdentity(origId);
826 if (stack.mConfigWillChange) {
827 // If the caller also wants to switch to a new configuration,
828 // do so now. This allows a clean switch, as we are waiting
829 // for the current activity to pause (so we will not destroy
830 // it), and have not yet started the next activity.
831 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
832 "updateConfiguration()");
833 stack.mConfigWillChange = false;
834 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
835 "Updating to new configuration after starting activity.");
836 mService.updateConfigurationLocked(globalConfig, null, false);
839 if (outResult != null) {
840 outResult.result = res;
841 if (res == ActivityManager.START_SUCCESS) {
842 mSupervisor.mWaitingActivityLaunched.add(outResult);
846 } catch (InterruptedException e) {
848 } while (outResult.result != START_TASK_TO_FRONT
849 && !outResult.timeout && outResult.who == null);
850 if (outResult.result == START_TASK_TO_FRONT) {
851 res = START_TASK_TO_FRONT;
854 if (res == START_TASK_TO_FRONT) {
855 final ActivityRecord r = outRecord[0];
857 // ActivityRecord may represent a different activity, but it should not be in
858 // the resumed state.
859 if (r.nowVisible && r.state == RESUMED) {
860 outResult.timeout = false;
861 outResult.who = r.realActivity;
862 outResult.totalTime = 0;
863 outResult.thisTime = 0;
865 outResult.thisTime = SystemClock.uptimeMillis();
866 mSupervisor.waitActivityVisible(r.realActivity, outResult);
867 // Note: the timeout variable is not currently not ever set.
871 } catch (InterruptedException e) {
873 } while (!outResult.timeout && outResult.who == null);
878 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
883 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
884 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
885 Bundle bOptions, int userId, String reason) {
886 if (intents == null) {
887 throw new NullPointerException("intents is null");
889 if (resolvedTypes == null) {
890 throw new NullPointerException("resolvedTypes is null");
892 if (intents.length != resolvedTypes.length) {
893 throw new IllegalArgumentException("intents are length different than resolvedTypes");
896 final int realCallingPid = Binder.getCallingPid();
897 final int realCallingUid = Binder.getCallingUid();
900 if (callingUid >= 0) {
902 } else if (caller == null) {
903 callingPid = realCallingPid;
904 callingUid = realCallingUid;
906 callingPid = callingUid = -1;
908 final long origId = Binder.clearCallingIdentity();
910 synchronized (mService) {
911 ActivityRecord[] outActivity = new ActivityRecord[1];
912 for (int i=0; i<intents.length; i++) {
913 Intent intent = intents[i];
914 if (intent == null) {
918 // Refuse possible leaked file descriptors
919 if (intent != null && intent.hasFileDescriptors()) {
920 throw new IllegalArgumentException("File descriptors passed in Intent");
923 boolean componentSpecified = intent.getComponent() != null;
925 // Don't modify the client's object!
926 intent = new Intent(intent);
928 // Collect information about the target of the Intent.
929 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
931 // TODO: New, check if this is correct
932 aInfo = mService.getActivityInfoForUser(aInfo, userId);
935 (aInfo.applicationInfo.privateFlags
936 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
937 throw new IllegalArgumentException(
938 "FLAG_CANT_SAVE_STATE not supported here");
941 ActivityOptions options = ActivityOptions.fromBundle(
942 i == intents.length - 1 ? bOptions : null);
943 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
944 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
945 callingPid, callingUid, callingPackage,
946 realCallingPid, realCallingUid, 0,
947 options, false, componentSpecified, outActivity, null, reason);
952 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
956 Binder.restoreCallingIdentity(origId);
959 return START_SUCCESS;
962 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
963 boolean sendHint = forceSend;
966 // If not forced, send power hint when the activity's process is different than the
967 // current resumed activity.
968 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
969 sendHint = resumedActivity == null
970 || resumedActivity.app == null
971 || !resumedActivity.app.equals(targetActivity.app);
974 if (sendHint && mService.mLocalPowerManager != null) {
975 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
976 mPowerHintSent = true;
980 void sendPowerHintForLaunchEndIfNeeded() {
981 // Trigger launch power hint if activity is launched
982 if (mPowerHintSent && mService.mLocalPowerManager != null) {
983 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
984 mPowerHintSent = false;
988 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
989 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
990 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
991 ActivityRecord[] outActivity) {
992 int result = START_CANCELED;
994 mService.mWindowManager.deferSurfaceLayout();
995 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
996 startFlags, doResume, options, inTask, outActivity);
998 // If we are not able to proceed, disassociate the activity from the task. Leaving an
999 // activity in an incomplete state can lead to issues, such as performing operations
1000 // without a window container.
1001 if (!ActivityManager.isStartResultSuccessful(result)
1002 && mStartActivity.getTask() != null) {
1003 mStartActivity.getTask().removeActivity(mStartActivity);
1005 mService.mWindowManager.continueSurfaceLayout();
1008 postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
1014 // Note: This method should only be called from {@link startActivity}.
1015 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1016 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1017 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1018 ActivityRecord[] outActivity) {
1020 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1023 computeLaunchingTaskFlags();
1025 computeSourceStack();
1027 mIntent.setFlags(mLaunchFlags);
1029 ActivityRecord reusedActivity = getReusableIntentActivity();
1031 final int preferredLaunchStackId =
1032 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1033 final int preferredLaunchDisplayId =
1034 (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
1036 if (reusedActivity != null) {
1037 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1038 // still needs to be a lock task mode violation since the task gets cleared out and
1039 // the device would otherwise leave the locked task.
1040 if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
1041 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1042 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1043 mSupervisor.showLockTaskToast();
1044 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1045 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1048 if (mStartActivity.getTask() == null) {
1049 mStartActivity.setTask(reusedActivity.getTask());
1051 if (reusedActivity.getTask().intent == null) {
1052 // This task was started because of movement of the activity based on affinity...
1053 // Now that we are actually launching it, we can assign the base intent.
1054 reusedActivity.getTask().setIntent(mStartActivity);
1057 // This code path leads to delivering a new intent, we want to make sure we schedule it
1058 // as the first operation, in case the activity will be resumed as a result of later
1060 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1061 || isDocumentLaunchesIntoExisting(mLaunchFlags)
1062 || mLaunchSingleInstance || mLaunchSingleTask) {
1063 final TaskRecord task = reusedActivity.getTask();
1065 // In this situation we want to remove all activities from the task up to the one
1066 // being started. In most cases this means we are resetting the task to its initial
1068 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1071 // The above code can remove {@code reusedActivity} from the task, leading to the
1072 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1073 // task reference is needed in the call below to
1074 // {@link setTargetStackAndMoveToFrontIfNeeded}.
1075 if (reusedActivity.getTask() == null) {
1076 reusedActivity.setTask(task);
1080 if (top.frontOfTask) {
1081 // Activity aliases may mean we use different intents for the top activity,
1082 // so make sure the task now has the identity of the new intent.
1083 top.getTask().setIntent(mStartActivity);
1085 deliverNewIntent(top);
1089 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
1091 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
1093 final ActivityRecord outResult =
1094 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1096 // When there is a reused activity and the current result is a trampoline activity,
1097 // set the reused activity as the result.
1098 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1099 outActivity[0] = reusedActivity;
1102 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1103 // We don't need to start a new activity, and the client said not to do anything
1104 // if that is the case, so this is it! And for paranoia, make sure we have
1105 // correctly resumed the top activity.
1106 resumeTargetStackIfNeeded();
1107 return START_RETURN_INTENT_TO_CALLER;
1109 setTaskFromIntentActivity(reusedActivity);
1111 if (!mAddingToTask && mReuseTask == null) {
1112 // We didn't do anything... but it was needed (a.k.a., client don't use that
1113 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1114 resumeTargetStackIfNeeded();
1115 if (outActivity != null && outActivity.length > 0) {
1116 outActivity[0] = reusedActivity;
1119 return START_TASK_TO_FRONT;
1123 if (mStartActivity.packageName == null) {
1124 final ActivityStack sourceStack = mStartActivity.resultTo != null
1125 ? mStartActivity.resultTo.getStack() : null;
1126 if (sourceStack != null) {
1127 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1128 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1131 ActivityOptions.abort(mOptions);
1132 return START_CLASS_NOT_FOUND;
1135 // If the activity being launched is the same as the one currently at the top, then
1136 // we need to check if it should only be launched once.
1137 final ActivityStack topStack = mSupervisor.mFocusedStack;
1138 final ActivityRecord topFocused = topStack.topActivity();
1139 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1140 final boolean dontStart = top != null && mStartActivity.resultTo == null
1141 && top.realActivity.equals(mStartActivity.realActivity)
1142 && top.userId == mStartActivity.userId
1143 && top.app != null && top.app.thread != null
1144 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1145 || mLaunchSingleTop || mLaunchSingleTask);
1147 // For paranoia, make sure we have correctly resumed the top activity.
1148 topStack.mLastPausedActivity = null;
1150 mSupervisor.resumeFocusedStackTopActivityLocked();
1152 ActivityOptions.abort(mOptions);
1153 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1154 // We don't need to start a new activity, and the client said not to do
1155 // anything if that is the case, so this is it!
1156 return START_RETURN_INTENT_TO_CALLER;
1159 deliverNewIntent(top);
1161 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1162 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1163 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
1164 preferredLaunchDisplayId, topStack.mStackId);
1166 return START_DELIVERED_TO_TOP;
1169 boolean newTask = false;
1170 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1171 ? mSourceRecord.getTask() : null;
1173 // Should this be considered a new task?
1174 int result = START_SUCCESS;
1175 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1176 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1178 result = setTaskFromReuseOrCreateNewTask(
1179 taskToAffiliate, preferredLaunchStackId, topStack);
1180 } else if (mSourceRecord != null) {
1181 result = setTaskFromSourceRecord();
1182 } else if (mInTask != null) {
1183 result = setTaskFromInTask();
1185 // This not being started from an existing activity, and not part of a new task...
1186 // just put it in the top task, though these days this case should never happen.
1187 setTaskToCurrentTopOrCreateNewTask();
1189 if (result != START_SUCCESS) {
1193 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1194 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1195 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1196 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
1197 if (mSourceRecord != null) {
1198 mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
1201 EventLog.writeEvent(
1202 EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1203 mStartActivity.getTask().taskId);
1205 ActivityStack.logStartActivity(
1206 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
1207 mTargetStack.mLastPausedActivity = null;
1209 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
1211 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1214 final ActivityRecord topTaskActivity =
1215 mStartActivity.getTask().topRunningActivityLocked();
1216 if (!mTargetStack.isFocusable()
1217 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1218 && mStartActivity != topTaskActivity)) {
1219 // If the activity is not focusable, we can't resume it, but still would like to
1220 // make sure it becomes visible as it starts (this will also trigger entry
1221 // animation). An example of this are PIP activities.
1222 // Also, we don't want to resume activities in a task that currently has an overlay
1223 // as the starting activity just needs to be in the visible paused state until the
1225 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1226 // Go ahead and tell window manager to execute app transition for this activity
1227 // since the app transition will not be triggered through the resume channel.
1228 mWindowManager.executeAppTransition();
1230 // If the target stack was not previously focusable (previous top running activity
1231 // on that stack was not visible) then any prior calls to move the stack to the
1232 // will not update the focused stack. If starting the new activity now allows the
1233 // task stack to be focusable, then ensure that we now update the focused stack
1235 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1236 mTargetStack.moveToFront("startActivityUnchecked");
1238 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1242 mTargetStack.addRecentActivityLocked(mStartActivity);
1244 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1246 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
1247 preferredLaunchDisplayId, mTargetStack.mStackId);
1249 return START_SUCCESS;
1252 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1253 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1254 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1260 mCallingUid = r.launchedFromUid;
1261 mSourceRecord = sourceRecord;
1262 mVoiceSession = voiceSession;
1263 mVoiceInteractor = voiceInteractor;
1265 mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
1267 mLaunchBounds = getOverrideBounds(r, options, inTask);
1269 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1270 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1271 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1272 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1273 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1274 mLaunchTaskBehind = r.mLaunchTaskBehind
1275 && !mLaunchSingleTask && !mLaunchSingleInstance
1276 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1278 sendNewTaskResultRequestIfNeeded();
1280 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1281 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1284 // If we are actually going to launch in to a new task, there are some cases where
1285 // we further want to do multiple task.
1286 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1287 if (mLaunchTaskBehind
1288 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1289 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1293 // We'll invoke onUserLeaving before onPause only if the launching
1294 // activity did not explicitly state that this is an automated launch.
1295 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1296 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1297 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1299 // If the caller has asked not to resume at this point, we make note
1300 // of this in the record so that we can skip it when trying to find
1301 // the top running activity.
1302 mDoResume = doResume;
1303 if (!doResume || !r.okToShowLocked()) {
1304 r.delayedResume = true;
1308 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1309 && mOptions.getTaskOverlay()) {
1310 r.mTaskOverlay = true;
1311 if (!mOptions.canTaskOverlayResume()) {
1312 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1313 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1314 if (top != null && top.state != RESUMED) {
1316 // The caller specifies that we'd like to be avoided to be moved to the front,
1319 mAvoidMoveToFront = true;
1324 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1327 // In some flows in to this function, we retrieve the task record and hold on to it
1328 // without a lock before calling back in to here... so the task at this point may
1329 // not actually be in recents. Check for that, and if it isn't in recents just
1330 // consider it invalid.
1331 if (inTask != null && !inTask.inRecents) {
1332 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1336 mStartFlags = startFlags;
1337 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1338 // is the same as the one making the call... or, as a special case, if we do not know
1339 // the caller then we count the current top activity as the caller.
1340 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1341 ActivityRecord checkedCaller = sourceRecord;
1342 if (checkedCaller == null) {
1343 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1346 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1347 // Caller is not the same as launcher, so always needed.
1348 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1352 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1355 private void sendNewTaskResultRequestIfNeeded() {
1356 final ActivityStack sourceStack = mStartActivity.resultTo != null
1357 ? mStartActivity.resultTo.getStack() : null;
1358 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1359 // For whatever reason this activity is being launched into a new task...
1360 // yet the caller has requested a result back. Well, that is pretty messed up,
1361 // so instead immediately send back a cancel and let the new task continue launched
1362 // as normal without a dependency on its originator.
1363 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1364 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1365 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1367 mStartActivity.resultTo = null;
1371 private void computeLaunchingTaskFlags() {
1372 // If the caller is not coming from another activity, but has given us an explicit task into
1373 // which they would like us to launch the new activity, then let's see about doing that.
1374 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
1375 final Intent baseIntent = mInTask.getBaseIntent();
1376 final ActivityRecord root = mInTask.getRootActivity();
1377 if (baseIntent == null) {
1378 ActivityOptions.abort(mOptions);
1379 throw new IllegalArgumentException("Launching into task without base intent: "
1383 // If this task is empty, then we are adding the first activity -- it
1384 // determines the root, and must be launching as a NEW_TASK.
1385 if (mLaunchSingleInstance || mLaunchSingleTask) {
1386 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1387 ActivityOptions.abort(mOptions);
1388 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1389 + mStartActivity + " into different task " + mInTask);
1392 ActivityOptions.abort(mOptions);
1393 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1394 + " has root " + root + " but target is singleInstance/Task");
1398 // If task is empty, then adopt the interesting intent launch flags in to the
1399 // activity being started.
1401 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1402 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1403 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1404 | (baseIntent.getFlags() & flagsOfInterest);
1405 mIntent.setFlags(mLaunchFlags);
1406 mInTask.setIntent(mStartActivity);
1407 mAddingToTask = true;
1409 // If the task is not empty and the caller is asking to start it as the root of
1410 // a new task, then we don't actually want to start this on the task. We will
1411 // bring the task to the front, and possibly give it a new intent.
1412 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1413 mAddingToTask = false;
1416 mAddingToTask = true;
1419 mReuseTask = mInTask;
1422 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1423 // when in freeform workspace.
1424 // Also put noDisplay activities in the source task. These by itself can be placed
1425 // in any task/stack, however it could launch other activities like ResolverActivity,
1426 // and we want those to stay in the original task.
1427 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1428 && mSourceRecord.isFreeform()) {
1429 mAddingToTask = true;
1433 if (mInTask == null) {
1434 if (mSourceRecord == null) {
1435 // This activity is not being started from another... in this
1436 // case we -always- start a new task.
1437 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1438 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1439 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1440 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1442 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1443 // The original activity who is starting us is running as a single
1444 // instance... this new activity it is starting must go on its
1446 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1447 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1448 // The activity being started is a single instance... it always
1449 // gets launched into its own task.
1450 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1455 private void computeSourceStack() {
1456 if (mSourceRecord == null) {
1457 mSourceStack = null;
1460 if (!mSourceRecord.finishing) {
1461 mSourceStack = mSourceRecord.getStack();
1465 // If the source is finishing, we can't further count it as our source. This is because the
1466 // task it is associated with may now be empty and on its way out, so we don't want to
1467 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1468 // a task for it. But save the task information so it can be used when creating the new task.
1469 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1470 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1471 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1472 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1473 mNewTaskInfo = mSourceRecord.info;
1475 // It is not guaranteed that the source record will have a task associated with it. For,
1476 // example, if this method is being called for processing a pending activity launch, it
1477 // is possible that the activity has been removed from the task after the launch was
1479 final TaskRecord sourceTask = mSourceRecord.getTask();
1480 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
1482 mSourceRecord = null;
1483 mSourceStack = null;
1487 * Decide whether the new activity should be inserted into an existing task. Returns null
1488 * if not or an ActivityRecord with the task into which the new activity should be added.
1490 private ActivityRecord getReusableIntentActivity() {
1491 // We may want to try to place the new activity in to an existing task. We always
1492 // do this if the target activity is singleTask or singleInstance; we will also do
1493 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1494 // us to still place it in a new task: multi task, always doc mode, or being asked to
1495 // launch this as a new task behind the current one.
1496 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1497 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1498 || mLaunchSingleInstance || mLaunchSingleTask;
1499 // If bring to front is requested, and no result is requested and we have not been given
1500 // an explicit task to launch in to, and we can find a task that was started with this
1501 // same component, then instead of launching bring that one to the front.
1502 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1503 ActivityRecord intentActivity = null;
1504 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1505 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1506 intentActivity = task != null ? task.getTopActivity() : null;
1507 } else if (putIntoExistingTask) {
1508 if (mLaunchSingleInstance) {
1509 // There can be one and only one instance of single instance activity in the
1510 // history, and it is always in its own unique task, so we do a special search.
1511 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1512 mStartActivity.isHomeActivity());
1513 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1514 // For the launch adjacent case we only want to put the activity in an existing
1515 // task if the activity already exists in the history.
1516 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1517 !mLaunchSingleTask);
1519 // Otherwise find the best task to put the activity in.
1520 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
1523 return intentActivity;
1527 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1528 * then return the Vr mode's virtual display ID. If not, if the source activity has
1529 * a explicit display ID set, use that to launch the activity.
1531 private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
1532 // Check if the Activity is a VR activity. If so, the activity should be launched in
1534 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1535 return DEFAULT_DISPLAY;
1538 // Get the virtual display id from ActivityManagerService.
1539 int displayId = mService.mVr2dDisplayId;
1540 if (displayId != INVALID_DISPLAY) {
1542 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1544 mUsingVr2dDisplay = true;
1548 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1549 // If the activity has a displayId set explicitly, launch it on the same displayId.
1550 if (displayId != INVALID_DISPLAY) {
1553 return DEFAULT_DISPLAY;
1557 * Figure out which task and activity to bring to front when we have found an existing matching
1558 * activity record in history. May also clear the task if needed.
1559 * @param intentActivity Existing matching activity.
1560 * @return {@link ActivityRecord} brought to front.
1562 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1563 mTargetStack = intentActivity.getStack();
1564 mTargetStack.mLastPausedActivity = null;
1565 // If the target task is not in the front, then we need to bring it to the front...
1566 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1567 // the same behavior as if a new instance was being started, which means not bringing it
1568 // to the front if the caller is not itself in the front.
1569 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1570 ActivityRecord curTop = (focusStack == null)
1571 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1573 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1575 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
1576 && !mAvoidMoveToFront) {
1577 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1578 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1579 mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
1580 // We really do want to push this one into the user's face, right now.
1581 if (mLaunchTaskBehind && mSourceRecord != null) {
1582 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
1584 mMovedOtherTask = true;
1586 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1587 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1588 // So no point resuming any of the activities here, it just wastes one extra
1589 // resuming, plus enter AND exit transitions.
1590 // Here we only want to bring the target stack forward. Transition will be applied
1591 // to the new activity that's started after the old ones are gone.
1592 final boolean willClearTask =
1593 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1594 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1595 if (!willClearTask) {
1596 final ActivityStack launchStack = getLaunchStack(
1597 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1598 final TaskRecord intentTask = intentActivity.getTask();
1599 if (launchStack == null || launchStack == mTargetStack) {
1600 // We only want to move to the front, if we aren't going to launch on a
1601 // different stack. If we launch on a different stack, we will put the
1602 // task on top there.
1603 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1604 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1605 mMovedToFront = true;
1606 } else if (launchStack.mStackId == DOCKED_STACK_ID
1607 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1608 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1609 // If we want to launch adjacent and mTargetStack is not the computed
1610 // launch stack - move task to top of computed stack.
1611 intentTask.reparent(launchStack.mStackId, ON_TOP,
1612 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1615 // TODO: This should be reevaluated in MW v2.
1616 // We choose to move task to front instead of launching it adjacent
1617 // when specific stack was requested explicitly and it appeared to be
1618 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1619 mTargetStack.moveTaskToFrontLocked(intentTask,
1620 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
1621 "bringToFrontInsteadOfAdjacentLaunch");
1623 mMovedToFront = true;
1624 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1625 // Target and computed stacks are on different displays and we've
1626 // found a matching task - move the existing instance to that display and
1627 // move it to front.
1628 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
1629 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1630 "reparentToDisplay");
1631 mMovedToFront = true;
1632 } else if (launchStack.getStackId() == StackId.HOME_STACK_ID
1633 && mTargetStack.getStackId() != StackId.HOME_STACK_ID) {
1634 // It is possible for the home activity to be in another stack initially.
1635 // For example, the activity may have been initially started with an intent
1636 // which placed it in the fullscreen stack. To ensure the proper handling of
1637 // the activity based on home stack assumptions, we must move it over.
1638 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
1639 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1641 mMovedToFront = true;
1645 // We are moving a task to the front, use starting window to hide initial drawn
1647 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1648 true /* taskSwitch */);
1650 updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
1653 if (!mMovedToFront && mDoResume) {
1654 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1655 + " from " + intentActivity);
1656 mTargetStack.moveToFront("intentActivityFound");
1659 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
1660 DEFAULT_DISPLAY, mTargetStack.mStackId);
1662 // If the caller has requested that the target task be reset, then do so.
1663 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1664 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1666 return intentActivity;
1669 private void updateTaskReturnToType(
1670 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1671 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1672 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1673 // Caller wants to appear on home activity.
1674 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1676 } else if (focusedStack == null || focusedStack.isHomeStack()) {
1677 // Task will be launched over the home stack, so return home.
1678 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1680 } else if (focusedStack != null && focusedStack != task.getStack() &&
1681 focusedStack.isAssistantStack()) {
1682 // Task was launched over the assistant stack, so return there
1683 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1687 // Else we are coming from an application stack so return to an application.
1688 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1691 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1692 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1693 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1694 // The caller has requested to completely replace any existing task with its new
1695 // activity. Well that should not be too hard...
1696 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1697 // removed from calling performClearTaskLocked (For example, if it is being brought out
1698 // of history or if it is finished immediately), thus disassociating the task. Also note
1699 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1700 // launching another activity.
1701 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1702 // already launching one.
1703 final TaskRecord task = intentActivity.getTask();
1704 task.performClearTaskLocked();
1706 mReuseTask.setIntent(mStartActivity);
1708 // When we clear the task - focus will be adjusted, which will bring another task
1709 // to top before we launch the activity we need. This will temporary swap their
1710 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1711 mMovedOtherTask = true;
1712 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1713 || mLaunchSingleInstance || mLaunchSingleTask) {
1714 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
1717 // A special case: we need to start the activity because it is not currently
1718 // running, and the caller has asked to clear the current task to have this
1719 // activity at the top.
1720 mAddingToTask = true;
1722 // We are no longer placing the activity in the task we previously thought we were.
1723 mStartActivity.setTask(null);
1724 // Now pretend like this activity is being started by the top of its task, so it
1725 // is put in the right place.
1726 mSourceRecord = intentActivity;
1727 final TaskRecord task = mSourceRecord.getTask();
1728 if (task != null && task.getStack() == null) {
1729 // Target stack got cleared when we all activities were removed above.
1730 // Go ahead and reset it.
1731 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1732 null /* bounds */, mLaunchFlags, mOptions);
1733 mTargetStack.addTask(task,
1734 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1737 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
1738 // In this case the top activity on the task is the same as the one being launched,
1739 // so we take that as a request to bring the task to the foreground. If the top
1740 // activity in the task is the root activity, deliver this new intent to it if it
1742 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1743 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1744 if (intentActivity.frontOfTask) {
1745 intentActivity.getTask().setIntent(mStartActivity);
1747 deliverNewIntent(intentActivity);
1748 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
1749 // In this case we are launching the root activity of the task, but with a
1750 // different intent. We should start a new instance on top.
1751 mAddingToTask = true;
1752 mSourceRecord = intentActivity;
1754 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1755 // In this case an activity is being launched in to an existing task, without
1756 // resetting that task. This is typically the situation of launching an activity
1757 // from a notification or shortcut. We want to place the new activity on top of the
1759 mAddingToTask = true;
1760 mSourceRecord = intentActivity;
1761 } else if (!intentActivity.getTask().rootWasReset) {
1762 // In this case we are launching into an existing task that has not yet been started
1763 // from its front door. The current task has been brought to the front. Ideally,
1764 // we'd probably like to place this new task at the bottom of its stack, but that's
1765 // a little hard to do with the current organization of the code so for now we'll
1767 intentActivity.getTask().setIntent(mStartActivity);
1771 private void resumeTargetStackIfNeeded() {
1773 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1775 ActivityOptions.abort(mOptions);
1777 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1780 private int setTaskFromReuseOrCreateNewTask(
1781 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1782 mTargetStack = computeStackFocus(
1783 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1785 // Do no move the target stack to front yet, as we might bail if
1786 // isLockTaskModeViolation fails below.
1788 if (mReuseTask == null) {
1789 final TaskRecord task = mTargetStack.createTaskRecord(
1790 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1791 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1792 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1793 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
1794 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
1795 if (mLaunchBounds != null) {
1796 final int stackId = mTargetStack.mStackId;
1797 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1798 mService.resizeStack(
1799 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1801 mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
1804 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1805 + " in new task " + mStartActivity.getTask());
1807 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1810 if (taskToAffiliate != null) {
1811 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
1814 if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
1815 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1816 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1819 if (!mMovedOtherTask) {
1820 // If stack id is specified in activity options, usually it means that activity is
1821 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1822 // that case we check the target stack.
1823 updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
1824 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1827 mTargetStack.moveToFront("reuseOrNewTask");
1829 return START_SUCCESS;
1832 private void deliverNewIntent(ActivityRecord activity) {
1833 if (mIntentDelivered) {
1837 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
1838 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1839 mStartActivity.launchedFromPackage);
1840 mIntentDelivered = true;
1843 private int setTaskFromSourceRecord() {
1844 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
1845 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1846 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1849 final TaskRecord sourceTask = mSourceRecord.getTask();
1850 final ActivityStack sourceStack = mSourceRecord.getStack();
1851 // We only want to allow changing stack in two cases:
1852 // 1. If the target task is not the top one. Otherwise we would move the launching task to
1853 // the other side, rather than show two side by side.
1854 // 2. If activity is not allowed on target display.
1855 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
1856 : sourceStack.mDisplayId;
1857 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
1858 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
1859 if (moveStackAllowed) {
1860 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
1862 // If target stack is not found now - we can't just rely on the source stack, as it may
1863 // be not suitable. Let's check other displays.
1864 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
1865 // Can't use target display, lets find a stack on the source display.
1866 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
1867 sourceStack.mDisplayId, mStartActivity);
1869 if (mTargetStack == null) {
1870 // There are no suitable stacks on the target and source display(s). Look on all
1872 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
1873 mStartActivity, -1 /* currentFocus */);
1877 if (mTargetStack == null) {
1878 mTargetStack = sourceStack;
1879 } else if (mTargetStack != sourceStack) {
1880 sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1881 !ANIMATE, DEFER_RESUME, "launchToSide");
1884 final TaskRecord topTask = mTargetStack.topTask();
1885 if (topTask != sourceTask && !mAvoidMoveToFront) {
1886 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1887 mStartActivity.appTimeTracker, "sourceTaskToFront");
1888 } else if (mDoResume) {
1889 mTargetStack.moveToFront("sourceStackToFront");
1892 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1893 // In this case, we are adding the activity to an existing task, but the caller has
1894 // asked to clear that task if the activity is already running.
1895 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1896 mKeepCurTransition = true;
1898 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
1899 deliverNewIntent(top);
1900 // For paranoia, make sure we have correctly resumed the top activity.
1901 mTargetStack.mLastPausedActivity = null;
1903 mSupervisor.resumeFocusedStackTopActivityLocked();
1905 ActivityOptions.abort(mOptions);
1906 return START_DELIVERED_TO_TOP;
1908 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1909 // In this case, we are launching an activity in our own task that may already be
1910 // running somewhere in the history, and we want to shuffle it to the front of the
1912 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1914 final TaskRecord task = top.getTask();
1915 task.moveActivityToFrontLocked(top);
1916 top.updateOptionsLocked(mOptions);
1917 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1918 deliverNewIntent(top);
1919 mTargetStack.mLastPausedActivity = null;
1921 mSupervisor.resumeFocusedStackTopActivityLocked();
1923 return START_DELIVERED_TO_TOP;
1927 // An existing activity is starting this new activity, so we want to keep the new one in
1928 // the same task as the one that is starting it.
1929 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
1930 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1931 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
1932 return START_SUCCESS;
1935 private int setTaskFromInTask() {
1936 // The caller is asking that the new activity be started in an explicit
1937 // task it has provided to us.
1938 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1939 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1940 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1943 mTargetStack = mInTask.getStack();
1945 // Check whether we should actually launch the new activity in to the task,
1946 // or just reuse the current activity on top.
1947 ActivityRecord top = mInTask.getTopActivity();
1948 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1949 && top.userId == mStartActivity.userId) {
1950 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1951 || mLaunchSingleTop || mLaunchSingleTask) {
1952 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1953 mStartActivity.appTimeTracker, "inTaskToFront");
1954 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1955 // We don't need to start a new activity, and the client said not to do
1956 // anything if that is the case, so this is it!
1957 return START_RETURN_INTENT_TO_CALLER;
1959 deliverNewIntent(top);
1960 return START_DELIVERED_TO_TOP;
1964 if (!mAddingToTask) {
1965 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1966 mStartActivity.appTimeTracker, "inTaskToFront");
1967 // We don't actually want to have this activity added to the task, so just
1968 // stop here but still tell the caller that we consumed the intent.
1969 ActivityOptions.abort(mOptions);
1970 return START_TASK_TO_FRONT;
1973 if (mLaunchBounds != null) {
1974 mInTask.updateOverrideConfiguration(mLaunchBounds);
1975 int stackId = mInTask.getLaunchStackId();
1976 if (stackId != mInTask.getStackId()) {
1977 mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1978 DEFER_RESUME, "inTaskToFront");
1979 stackId = mInTask.getStackId();
1980 mTargetStack = mInTask.getStack();
1982 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1983 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1987 mTargetStack.moveTaskToFrontLocked(
1988 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1990 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1991 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1992 + " in explicit task " + mStartActivity.getTask());
1994 return START_SUCCESS;
1997 private void setTaskToCurrentTopOrCreateNewTask() {
1998 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
2001 mTargetStack.moveToFront("addingToTopTask");
2003 final ActivityRecord prev = mTargetStack.topActivity();
2004 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
2005 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
2006 mIntent, null, null, true, mStartActivity.mActivityType);
2007 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2008 mTargetStack.positionChildWindowContainerAtTop(task);
2009 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2010 + " in new guessed " + mStartActivity.getTask());
2013 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
2014 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
2015 parent.addActivityToTop(mStartActivity);
2017 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2021 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2022 boolean launchSingleTask, int launchFlags) {
2023 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2024 (launchSingleInstance || launchSingleTask)) {
2025 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2026 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2027 "\"singleInstance\" or \"singleTask\"");
2029 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2031 switch (r.info.documentLaunchMode) {
2032 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2034 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2035 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2037 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2038 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2040 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2041 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2048 final void doPendingActivityLaunchesLocked(boolean doResume) {
2049 while (!mPendingActivityLaunches.isEmpty()) {
2050 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
2051 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
2053 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
2054 null, null /*outRecords*/);
2055 } catch (Exception e) {
2056 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
2057 pal.sendErrorResult(e.getMessage());
2062 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
2063 int launchFlags, ActivityOptions aOptions) {
2064 final TaskRecord task = r.getTask();
2065 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
2066 if (stack != null) {
2070 final ActivityStack currentStack = task != null ? task.getStack() : null;
2071 if (currentStack != null) {
2072 if (mSupervisor.mFocusedStack != currentStack) {
2073 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2074 "computeStackFocus: Setting " + "focused stack to r=" + r
2077 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2078 "computeStackFocus: Focused stack already="
2079 + mSupervisor.mFocusedStack);
2081 return currentStack;
2084 if (canLaunchIntoFocusedStack(r, newTask)) {
2085 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2086 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2087 return mSupervisor.mFocusedStack;
2090 if (mSourceDisplayId != DEFAULT_DISPLAY) {
2091 // Try to put the activity in a stack on a secondary display.
2092 stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2093 if (stack == null) {
2094 // If source display is not suitable - look for topmost valid stack in the system.
2095 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2096 "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
2097 + ", looking on all displays.");
2098 stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
2101 if (stack == null) {
2102 // We first try to put the task in the first dynamic stack on home display.
2103 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2104 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2105 stack = homeDisplayStacks.get(stackNdx);
2106 if (isDynamicStack(stack.mStackId)) {
2107 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2108 "computeStackFocus: Setting focused stack=" + stack);
2112 // If there is no suitable dynamic stack then we figure out which static stack to use.
2113 final int stackId = task != null ? task.getLaunchStackId() :
2114 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2115 FULLSCREEN_WORKSPACE_STACK_ID;
2116 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
2118 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2119 + r + " stackId=" + stack.mStackId);
2123 /** Check if provided activity record can launch in currently focused stack. */
2124 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
2125 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2126 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2127 final boolean canUseFocusedStack;
2128 switch (focusedStackId) {
2129 case FULLSCREEN_WORKSPACE_STACK_ID:
2130 // The fullscreen stack can contain any task regardless of if the task is resizeable
2131 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
2132 canUseFocusedStack = true;
2134 case ASSISTANT_STACK_ID:
2135 canUseFocusedStack = r.isAssistantActivity();
2137 case DOCKED_STACK_ID:
2138 // Any activity which supports split screen can go in the docked stack.
2139 canUseFocusedStack = r.supportsSplitScreen();
2141 case FREEFORM_WORKSPACE_STACK_ID:
2142 // Any activity which supports freeform can go in the freeform stack.
2143 canUseFocusedStack = r.supportsFreeform();
2146 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2148 canUseFocusedStack = isDynamicStack(focusedStackId)
2149 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2152 return canUseFocusedStack && !newTask
2153 // We strongly prefer to launch activities on the same display as their source.
2154 && (mSourceDisplayId == focusedStack.mDisplayId);
2157 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
2158 ActivityOptions aOptions) {
2159 // We are reusing a task, keep the stack!
2160 if (mReuseTask != null) {
2161 return mReuseTask.getStack();
2164 // If the activity is of a specific type, return the associated stack, creating it if
2166 if (r.isHomeActivity()) {
2167 return mSupervisor.mHomeStack;
2169 if (r.isRecentsActivity()) {
2170 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2172 if (r.isAssistantActivity()) {
2173 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2176 final int launchDisplayId =
2177 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2179 final int launchStackId =
2180 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2182 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2183 throw new IllegalArgumentException(
2184 "Stack and display id can't be set at the same time.");
2187 if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
2188 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
2190 if (launchStackId == DOCKED_STACK_ID) {
2191 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2192 // for this activity, so we put the activity in the fullscreen stack.
2193 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2195 if (launchDisplayId != INVALID_DISPLAY) {
2196 // Stack id has higher priority than display id.
2197 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2200 // If we are using Vr2d display, find the virtual display stack.
2201 if (mUsingVr2dDisplay) {
2202 ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2204 Slog.v(TAG, "Launch stack for app: " + r.toString() +
2205 ", on virtual display stack:" + as.toString());
2210 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2211 || mSourceDisplayId != DEFAULT_DISPLAY) {
2214 // Otherwise handle adjacent launch.
2216 // The parent activity doesn't want to launch the activity on top of itself, but
2217 // instead tries to put it onto other side in side-by-side mode.
2218 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
2220 if (parentStack != mSupervisor.mFocusedStack) {
2221 // If task's parent stack is not focused - use it during adjacent launch.
2224 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2225 // If task is already on top of focused stack - use it. We don't want to move the
2226 // existing focused task to adjacent stack, just deliver new intent in this case.
2227 return mSupervisor.mFocusedStack;
2230 if (parentStack != null && parentStack.isDockedStack()) {
2231 // If parent was in docked stack, the natural place to launch another activity
2232 // will be fullscreen, so it can appear alongside the docked window.
2233 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2236 // If the parent is not in the docked stack, we check if there is docked window
2237 // and if yes, we will launch into that stack. If not, we just put the new
2238 // activity into parent's stack, because we can't find a better place.
2239 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2240 if (dockedStack != null
2241 && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
2242 // There is a docked stack, but it isn't visible, so we can't launch into that.
2251 boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
2253 case INVALID_STACK_ID:
2256 case FULLSCREEN_WORKSPACE_STACK_ID:
2258 case FREEFORM_WORKSPACE_STACK_ID:
2259 return r.supportsFreeform();
2260 case DOCKED_STACK_ID:
2261 return r.supportsSplitScreen();
2262 case PINNED_STACK_ID:
2263 return r.supportsPictureInPicture();
2264 case RECENTS_STACK_ID:
2265 return r.isRecentsActivity();
2266 case ASSISTANT_STACK_ID:
2267 return r.isAssistantActivity();
2269 if (StackId.isDynamicStack(stackId)) {
2270 return r.canBeLaunchedOnDisplay(displayId);
2272 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2277 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2278 Rect newBounds = null;
2279 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2280 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2281 options, options.getLaunchStackId())) {
2282 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2288 void setWindowManager(WindowManagerService wm) {
2289 mWindowManager = wm;
2292 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2293 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2294 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2295 if (pal.stack == stack) {
2296 mPendingActivityLaunches.remove(palNdx);
2301 static boolean isDocumentLaunchesIntoExisting(int flags) {
2302 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2303 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2306 boolean clearPendingActivityLaunchesLocked(String packageName) {
2307 boolean didSomething = false;
2309 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2310 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2311 ActivityRecord r = pal.r;
2312 if (r != null && r.packageName.equals(packageName)) {
2313 mPendingActivityLaunches.remove(palNdx);
2314 didSomething = true;
2317 return didSomething;
2320 void dump(PrintWriter pw, String prefix, String dumpPackage) {
2321 prefix = prefix + " ";
2323 if (dumpPackage != null) {
2324 if ((mLastStartActivityRecord[0] == null ||
2325 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2326 (mLastHomeActivityStartRecord[0] == null ||
2327 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2328 (mStartActivity == null || !dumpPackage.equals(mStartActivity.packageName))) {
2330 pw.println("(nothing)");
2336 pw.print("mCurrentUser=");
2337 pw.println(mSupervisor.mCurrentUser);
2339 pw.print("mLastStartReason=");
2340 pw.println(mLastStartReason);
2342 pw.print("mLastStartActivityTimeMs=");
2343 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2345 pw.print("mLastStartActivityResult=");
2346 pw.println(mLastStartActivityResult);
2347 ActivityRecord r = mLastStartActivityRecord[0];
2350 pw.println("mLastStartActivityRecord:");
2351 r.dump(pw, prefix + " ");
2354 pw.print("mLastHomeActivityStartResult=");
2355 pw.println(mLastHomeActivityStartResult);
2356 r = mLastHomeActivityStartRecord[0];
2359 pw.println("mLastHomeActivityStartRecord:");
2360 r.dump(pw, prefix + " ");
2362 if (mStartActivity != null) {
2364 pw.println("mStartActivity:");
2365 mStartActivity.dump(pw, prefix + " ");
2367 if (mIntent != null) {
2369 pw.print("mIntent=");
2370 pw.println(mIntent);
2372 if (mOptions != null) {
2374 pw.print("mOptions=");
2375 pw.println(mOptions);
2378 pw.print("mLaunchSingleTop=");
2379 pw.print(mLaunchSingleTop);
2380 pw.print(" mLaunchSingleInstance=");
2381 pw.print(mLaunchSingleInstance);
2382 pw.print(" mLaunchSingleTask=");
2383 pw.println(mLaunchSingleTask);
2385 pw.print("mLaunchFlags=0x");
2386 pw.print(Integer.toHexString(mLaunchFlags));
2387 pw.print(" mDoResume=");
2388 pw.print(mDoResume);
2389 pw.print(" mAddingToTask=");
2390 pw.println(mAddingToTask);