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.WindowConfiguration.WINDOWING_MODE_FREEFORM;
30 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
31 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
32 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
33 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
34 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
35 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
36 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
37 import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
38 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
39 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
40 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
41 import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
42 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
43 import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
44 import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
45 import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
46 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
47 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
48 import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
49 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
50 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
51 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
52 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
53 import static android.view.Display.DEFAULT_DISPLAY;
54 import static android.view.Display.INVALID_DISPLAY;
55 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
56 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
57 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
58 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
59 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
60 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
61 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
62 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
63 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
64 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
65 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
66 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
67 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
68 import static com.android.server.am.ActivityManagerService.ANIMATE;
69 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
70 import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
71 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
72 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
73 import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
74 import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
75 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
76 import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
78 import android.annotation.NonNull;
79 import android.annotation.Nullable;
80 import android.app.ActivityManager;
81 import android.app.ActivityOptions;
82 import android.app.IApplicationThread;
83 import android.app.PendingIntent;
84 import android.app.ProfilerInfo;
85 import android.app.WaitResult;
86 import android.content.IIntentSender;
87 import android.content.Intent;
88 import android.content.IntentSender;
89 import android.content.pm.ActivityInfo;
90 import android.content.pm.ApplicationInfo;
91 import android.content.pm.AuxiliaryResolveInfo;
92 import android.content.pm.PackageManager;
93 import android.content.pm.ResolveInfo;
94 import android.content.pm.UserInfo;
95 import android.content.res.Configuration;
96 import android.graphics.Rect;
97 import android.os.Binder;
98 import android.os.Bundle;
99 import android.os.IBinder;
100 import android.os.RemoteException;
101 import android.os.SystemClock;
102 import android.os.Trace;
103 import android.os.UserHandle;
104 import android.os.UserManager;
105 import android.service.voice.IVoiceInteractionSession;
106 import android.text.TextUtils;
107 import android.util.EventLog;
108 import android.util.Pools.SynchronizedPool;
109 import android.util.Slog;
111 import com.android.internal.annotations.VisibleForTesting;
112 import com.android.internal.app.HeavyWeightSwitcherActivity;
113 import com.android.internal.app.IVoiceInteractor;
114 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
115 import com.android.server.am.LaunchParamsController.LaunchParams;
116 import com.android.server.pm.InstantAppResolver;
118 import java.io.PrintWriter;
119 import java.text.DateFormat;
120 import java.util.Date;
123 * Controller for interpreting how and then launching an activity.
125 * This class collects all the logic for determining how an intent and flags should be turned into
126 * an activity and associated task and stack.
128 class ActivityStarter {
129 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
130 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
131 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
132 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
133 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
134 private static final int INVALID_LAUNCH_MODE = -1;
136 private final ActivityManagerService mService;
137 private final ActivityStackSupervisor mSupervisor;
138 private final ActivityStartInterceptor mInterceptor;
139 private final ActivityStartController mController;
141 // Share state variable among methods when starting an activity.
142 private ActivityRecord mStartActivity;
143 private Intent mIntent;
144 private int mCallingUid;
145 private ActivityOptions mOptions;
147 private int mLaunchMode;
148 private boolean mLaunchTaskBehind;
149 private int mLaunchFlags;
151 private LaunchParams mLaunchParams = new LaunchParams();
153 private ActivityRecord mNotTop;
154 private boolean mDoResume;
155 private int mStartFlags;
156 private ActivityRecord mSourceRecord;
158 // The display to launch the activity onto, barring any strong reason to do otherwise.
159 private int mPreferredDisplayId;
161 private TaskRecord mInTask;
162 private boolean mAddingToTask;
163 private TaskRecord mReuseTask;
165 private ActivityInfo mNewTaskInfo;
166 private Intent mNewTaskIntent;
167 private ActivityStack mSourceStack;
168 private ActivityStack mTargetStack;
169 private boolean mMovedToFront;
170 private boolean mNoAnimation;
171 private boolean mKeepCurTransition;
172 private boolean mAvoidMoveToFront;
174 // We must track when we deliver the new intent since multiple code paths invoke
175 // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
176 // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
177 // delivered at most once.
178 private boolean mIntentDelivered;
180 private IVoiceInteractionSession mVoiceSession;
181 private IVoiceInteractor mVoiceInteractor;
183 // Last activity record we attempted to start
184 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
185 // The result of the last activity we attempted to start.
186 private int mLastStartActivityResult;
187 // Time in milli seconds we attempted to start the last activity.
188 private long mLastStartActivityTimeMs;
189 // The reason we were trying to start the last activity
190 private String mLastStartReason;
193 * Request details provided through setter methods. Should be reset after {@link #execute()}
194 * to avoid unnecessarily retaining parameters. Note that the request is ignored when
195 * {@link #startResolvedActivity} is invoked directly.
197 private Request mRequest = new Request();
200 * An interface that to provide {@link ActivityStarter} instances to the controller. This is
201 * used by tests to inject their own starter implementations for verification purposes.
206 * Sets the {@link ActivityStartController} to be passed to {@link ActivityStarter}.
208 void setController(ActivityStartController controller);
211 * Generates an {@link ActivityStarter} that is ready to handle a new start request.
212 * @param controller The {@link ActivityStartController} which the starter who will own
214 * @return an {@link ActivityStarter}
216 ActivityStarter obtain();
219 * Recycles a starter for reuse.
221 void recycle(ActivityStarter starter);
225 * Default implementation of {@link StarterFactory}.
227 static class DefaultFactory implements Factory {
229 * The maximum count of starters that should be active at one time:
230 * 1. last ran starter (for logging and post activity processing)
231 * 2. current running starter
232 * 3. starter from re-entry in (2)
234 private final int MAX_STARTER_COUNT = 3;
236 private ActivityStartController mController;
237 private ActivityManagerService mService;
238 private ActivityStackSupervisor mSupervisor;
239 private ActivityStartInterceptor mInterceptor;
241 private SynchronizedPool<ActivityStarter> mStarterPool =
242 new SynchronizedPool<>(MAX_STARTER_COUNT);
244 DefaultFactory(ActivityManagerService service,
245 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
247 mSupervisor = supervisor;
248 mInterceptor = interceptor;
252 public void setController(ActivityStartController controller) {
253 mController = controller;
257 public ActivityStarter obtain() {
258 ActivityStarter starter = mStarterPool.acquire();
260 if (starter == null) {
261 starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
268 public void recycle(ActivityStarter starter) {
269 starter.reset(true /* clearRequest*/);
270 mStarterPool.release(starter);
275 * Container for capturing initial start request details. This information is NOT reset until
276 * the {@link ActivityStarter} is recycled, allowing for multiple invocations with the same
279 * TODO(b/64750076): Investigate consolidating member variables of {@link ActivityStarter} with
280 * the request object. Note that some member variables are referenced in
281 * {@link #dump(PrintWriter, String)} and therefore cannot be cleared immediately after
284 private static class Request {
285 private static final int DEFAULT_CALLING_UID = -1;
286 private static final int DEFAULT_CALLING_PID = 0;
288 IApplicationThread caller;
290 Intent ephemeralIntent;
292 ActivityInfo activityInfo;
293 ResolveInfo resolveInfo;
294 IVoiceInteractionSession voiceSession;
295 IVoiceInteractor voiceInteractor;
299 int callingPid = DEFAULT_CALLING_UID;
300 int callingUid = DEFAULT_CALLING_PID;
301 String callingPackage;
305 SafeActivityOptions activityOptions;
306 boolean ignoreTargetSecurity;
307 boolean componentSpecified;
308 boolean avoidMoveToFront;
309 ActivityRecord[] outActivity;
312 ProfilerInfo profilerInfo;
313 Configuration globalConfig;
315 WaitResult waitResult;
316 int filterCallingUid;
317 PendingIntentRecord originatingPendingIntent;
320 * If set to {@code true}, allows this activity start to look into
321 * {@link PendingRemoteAnimationRegistry}
323 boolean allowPendingRemoteAnimationRegistryLookup;
326 * Indicates that we should wait for the result of the start request. This flag is set when
327 * {@link ActivityStarter#setMayWait(int)} is called.
328 * {@see ActivityStarter#startActivityMayWait}.
333 * Ensure constructed request matches reset instance.
340 * Sets values back to the initial state, clearing any held references.
345 ephemeralIntent = null;
350 voiceInteractor = null;
354 callingPid = DEFAULT_CALLING_PID;
355 callingUid = DEFAULT_CALLING_UID;
356 callingPackage = null;
360 activityOptions = null;
361 ignoreTargetSecurity = false;
362 componentSpecified = false;
371 avoidMoveToFront = false;
372 allowPendingRemoteAnimationRegistryLookup = true;
373 filterCallingUid = UserHandle.USER_NULL;
374 originatingPendingIntent = null;
378 * Adopts all values from passed in request.
380 void set(Request request) {
381 caller = request.caller;
382 intent = request.intent;
383 ephemeralIntent = request.ephemeralIntent;
384 resolvedType = request.resolvedType;
385 activityInfo = request.activityInfo;
386 resolveInfo = request.resolveInfo;
387 voiceSession = request.voiceSession;
388 voiceInteractor = request.voiceInteractor;
389 resultTo = request.resultTo;
390 resultWho = request.resultWho;
391 requestCode = request.requestCode;
392 callingPid = request.callingPid;
393 callingUid = request.callingUid;
394 callingPackage = request.callingPackage;
395 realCallingPid = request.realCallingPid;
396 realCallingUid = request.realCallingUid;
397 startFlags = request.startFlags;
398 activityOptions = request.activityOptions;
399 ignoreTargetSecurity = request.ignoreTargetSecurity;
400 componentSpecified = request.componentSpecified;
401 outActivity = request.outActivity;
402 inTask = request.inTask;
403 reason = request.reason;
404 profilerInfo = request.profilerInfo;
405 globalConfig = request.globalConfig;
406 userId = request.userId;
407 waitResult = request.waitResult;
408 mayWait = request.mayWait;
409 avoidMoveToFront = request.avoidMoveToFront;
410 allowPendingRemoteAnimationRegistryLookup
411 = request.allowPendingRemoteAnimationRegistryLookup;
412 filterCallingUid = request.filterCallingUid;
413 originatingPendingIntent = request.originatingPendingIntent;
417 ActivityStarter(ActivityStartController controller, ActivityManagerService service,
418 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
419 mController = controller;
421 mSupervisor = supervisor;
422 mInterceptor = interceptor;
427 * Effectively duplicates the starter passed in. All state and request values will be
431 void set(ActivityStarter starter) {
432 mStartActivity = starter.mStartActivity;
433 mIntent = starter.mIntent;
434 mCallingUid = starter.mCallingUid;
435 mOptions = starter.mOptions;
437 mLaunchTaskBehind = starter.mLaunchTaskBehind;
438 mLaunchFlags = starter.mLaunchFlags;
439 mLaunchMode = starter.mLaunchMode;
441 mLaunchParams.set(starter.mLaunchParams);
443 mNotTop = starter.mNotTop;
444 mDoResume = starter.mDoResume;
445 mStartFlags = starter.mStartFlags;
446 mSourceRecord = starter.mSourceRecord;
447 mPreferredDisplayId = starter.mPreferredDisplayId;
449 mInTask = starter.mInTask;
450 mAddingToTask = starter.mAddingToTask;
451 mReuseTask = starter.mReuseTask;
453 mNewTaskInfo = starter.mNewTaskInfo;
454 mNewTaskIntent = starter.mNewTaskIntent;
455 mSourceStack = starter.mSourceStack;
457 mTargetStack = starter.mTargetStack;
458 mMovedToFront = starter.mMovedToFront;
459 mNoAnimation = starter.mNoAnimation;
460 mKeepCurTransition = starter.mKeepCurTransition;
461 mAvoidMoveToFront = starter.mAvoidMoveToFront;
463 mVoiceSession = starter.mVoiceSession;
464 mVoiceInteractor = starter.mVoiceInteractor;
466 mIntentDelivered = starter.mIntentDelivered;
468 mRequest.set(starter.mRequest);
471 ActivityRecord getStartActivity() {
472 return mStartActivity;
475 boolean relatedToPackage(String packageName) {
476 return (mLastStartActivityRecord[0] != null
477 && packageName.equals(mLastStartActivityRecord[0].packageName))
478 || (mStartActivity != null && packageName.equals(mStartActivity.packageName));
482 * Starts an activity based on the request parameters provided earlier.
483 * @return The starter result.
487 // TODO(b/64750076): Look into passing request directly to these methods to allow
488 // for transactional diffs and preprocessing.
489 if (mRequest.mayWait) {
490 return startActivityMayWait(mRequest.caller, mRequest.callingUid,
491 mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
492 mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
493 mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
494 mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
495 mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
496 mRequest.inTask, mRequest.reason,
497 mRequest.allowPendingRemoteAnimationRegistryLookup,
498 mRequest.originatingPendingIntent);
500 return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
501 mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
502 mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
503 mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
504 mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
505 mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
506 mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
507 mRequest.outActivity, mRequest.inTask, mRequest.reason,
508 mRequest.allowPendingRemoteAnimationRegistryLookup,
509 mRequest.originatingPendingIntent);
512 onExecutionComplete();
517 * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
518 * Note that this method is called internally as well as part of {@link #startActivity}.
520 * @return The start result.
522 int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
523 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
524 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
525 ActivityRecord[] outActivity) {
527 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
528 doResume, options, inTask, outActivity);
530 onExecutionComplete();
534 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
535 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
536 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
537 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
538 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
539 SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
540 ActivityRecord[] outActivity, TaskRecord inTask, String reason,
541 boolean allowPendingRemoteAnimationRegistryLookup,
542 PendingIntentRecord originatingPendingIntent) {
544 if (TextUtils.isEmpty(reason)) {
545 throw new IllegalArgumentException("Need to specify a reason.");
547 mLastStartReason = reason;
548 mLastStartActivityTimeMs = System.currentTimeMillis();
549 mLastStartActivityRecord[0] = null;
551 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
552 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
553 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
554 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
555 inTask, allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);
557 if (outActivity != null) {
558 // mLastStartActivityRecord[0] is set in the call to startActivity above.
559 outActivity[0] = mLastStartActivityRecord[0];
562 return getExternalResult(mLastStartActivityResult);
565 static int getExternalResult(int result) {
566 // Aborted results are treated as successes externally, but we must track them internally.
567 return result != START_ABORTED ? result : START_SUCCESS;
571 * Called when execution is complete. Sets state indicating completion and proceeds with
572 * recycling if appropriate.
574 private void onExecutionComplete() {
575 mController.onExecutionComplete(this);
578 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
579 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
580 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
581 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
582 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
583 SafeActivityOptions options,
584 boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
585 TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
586 PendingIntentRecord originatingPendingIntent) {
587 int err = ActivityManager.START_SUCCESS;
588 // Pull the optional Ephemeral Installer-only bundle out of the options early.
589 final Bundle verificationBundle
590 = options != null ? options.popAppVerificationBundle() : null;
592 ProcessRecord callerApp = null;
593 if (caller != null) {
594 callerApp = mService.getRecordForAppLocked(caller);
595 if (callerApp != null) {
596 callingPid = callerApp.pid;
597 callingUid = callerApp.info.uid;
599 Slog.w(TAG, "Unable to find app for caller " + caller
600 + " (pid=" + callingPid + ") when starting: "
601 + intent.toString());
602 err = ActivityManager.START_PERMISSION_DENIED;
606 final int userId = aInfo != null && aInfo.applicationInfo != null
607 ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
609 if (err == ActivityManager.START_SUCCESS) {
610 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
611 + "} from uid " + callingUid);
614 ActivityRecord sourceRecord = null;
615 ActivityRecord resultRecord = null;
616 if (resultTo != null) {
617 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
618 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
619 "Will send result to " + resultTo + " " + sourceRecord);
620 if (sourceRecord != null) {
621 if (requestCode >= 0 && !sourceRecord.finishing) {
622 resultRecord = sourceRecord;
627 final int launchFlags = intent.getFlags();
629 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
630 // Transfer the result target from the source activity to the new
631 // one being started, including any failures.
632 if (requestCode >= 0) {
633 SafeActivityOptions.abort(options);
634 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
636 resultRecord = sourceRecord.resultTo;
637 if (resultRecord != null && !resultRecord.isInStackLocked()) {
640 resultWho = sourceRecord.resultWho;
641 requestCode = sourceRecord.requestCode;
642 sourceRecord.resultTo = null;
643 if (resultRecord != null) {
644 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
646 if (sourceRecord.launchedFromUid == callingUid) {
647 // The new activity is being launched from the same uid as the previous
648 // activity in the flow, and asking to forward its result back to the
649 // previous. In this case the activity is serving as a trampoline between
650 // the two, so we also want to update its launchedFromPackage to be the
651 // same as the previous activity. Note that this is safe, since we know
652 // these two packages come from the same uid; the caller could just as
653 // well have supplied that same package name itself. This specifially
654 // deals with the case of an intent picker/chooser being launched in the app
655 // flow to redirect to an activity picked by the user, where we want the final
656 // activity to consider it to have been launched by the previous app activity.
657 callingPackage = sourceRecord.launchedFromPackage;
661 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
662 // We couldn't find a class that can handle the given Intent.
663 // That's the end of that!
664 err = ActivityManager.START_INTENT_NOT_RESOLVED;
667 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
668 // We couldn't find the specific class specified in the Intent.
669 // Also the end of the line.
670 err = ActivityManager.START_CLASS_NOT_FOUND;
673 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
674 && sourceRecord.getTask().voiceSession != null) {
675 // If this activity is being launched as part of a voice session, we need
676 // to ensure that it is safe to do so. If the upcoming activity will also
677 // be part of the voice session, we can only launch it if it has explicitly
678 // said it supports the VOICE category, or it is a part of the calling app.
679 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
680 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
682 intent.addCategory(Intent.CATEGORY_VOICE);
683 if (!mService.getPackageManager().activitySupportsIntent(
684 intent.getComponent(), intent, resolvedType)) {
686 "Activity being started in current voice task does not support voice: "
688 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
690 } catch (RemoteException e) {
691 Slog.w(TAG, "Failure checking voice capabilities", e);
692 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
697 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
698 // If the caller is starting a new voice session, just make sure the target
699 // is actually allowing it to run this way.
701 if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
702 intent, resolvedType)) {
704 "Activity being started in new voice task does not support: "
706 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
708 } catch (RemoteException e) {
709 Slog.w(TAG, "Failure checking voice capabilities", e);
710 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
714 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
716 if (err != START_SUCCESS) {
717 if (resultRecord != null) {
718 resultStack.sendActivityResultLocked(
719 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
721 SafeActivityOptions.abort(options);
725 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
726 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
727 inTask != null, callerApp, resultRecord, resultStack);
728 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
729 callingPid, resolvedType, aInfo.applicationInfo);
731 // Merge the two options bundles, while realCallerOptions takes precedence.
732 ActivityOptions checkedOptions = options != null
733 ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
735 if (allowPendingRemoteAnimationRegistryLookup) {
736 checkedOptions = mService.getActivityStartController()
737 .getPendingRemoteAnimationRegistry()
738 .overrideOptionsIfNeeded(callingPackage, checkedOptions);
740 if (mService.mController != null) {
742 // The Intent we give to the watcher has the extra data
743 // stripped off, since it can contain private information.
744 Intent watchIntent = intent.cloneFilter();
745 abort |= !mService.mController.activityStarting(watchIntent,
746 aInfo.applicationInfo.packageName);
747 } catch (RemoteException e) {
748 mService.mController = null;
752 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
753 if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
754 callingUid, checkedOptions)) {
755 // activity start was intercepted, e.g. because the target user is currently in quiet
756 // mode (turn off work) or the target application is suspended
757 intent = mInterceptor.mIntent;
758 rInfo = mInterceptor.mRInfo;
759 aInfo = mInterceptor.mAInfo;
760 resolvedType = mInterceptor.mResolvedType;
761 inTask = mInterceptor.mInTask;
762 callingPid = mInterceptor.mCallingPid;
763 callingUid = mInterceptor.mCallingUid;
764 checkedOptions = mInterceptor.mActivityOptions;
768 if (resultRecord != null) {
769 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
770 RESULT_CANCELED, null);
772 // We pretend to the caller that it was really started, but
773 // they will just get a cancel result.
774 ActivityOptions.abort(checkedOptions);
775 return START_ABORTED;
778 // If permissions need a review before any of the app components can run, we
779 // launch the review activity and pass a pending intent to start the activity
780 // we are to launching now after the review is completed.
781 if (mService.mPermissionReviewRequired && aInfo != null) {
782 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
783 aInfo.packageName, userId)) {
784 IIntentSender target = mService.getIntentSenderLocked(
785 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
786 callingUid, userId, null, null, 0, new Intent[]{intent},
787 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
788 | PendingIntent.FLAG_ONE_SHOT, null);
790 final int flags = intent.getFlags();
791 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
792 newIntent.setFlags(flags
793 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
794 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
795 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
796 if (resultRecord != null) {
797 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
802 callingUid = realCallingUid;
803 callingPid = realCallingPid;
805 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
806 computeResolveFilterUid(
807 callingUid, realCallingUid, mRequest.filterCallingUid));
808 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
809 null /*profilerInfo*/);
811 if (DEBUG_PERMISSIONS_REVIEW) {
812 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
813 true, false) + "} from uid " + callingUid + " on display "
814 + (mSupervisor.mFocusedStack == null
815 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
820 // If we have an ephemeral app, abort the process of launching the resolved intent.
821 // Instead, launch the ephemeral installer. Once the installer is finished, it
822 // starts either the intent we resolved here [on install error] or the ephemeral
823 // app [on install success].
824 if (rInfo != null && rInfo.auxiliaryInfo != null) {
825 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
826 callingPackage, verificationBundle, resolvedType, userId);
828 callingUid = realCallingUid;
829 callingPid = realCallingPid;
831 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
834 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
835 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
836 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
837 mSupervisor, checkedOptions, sourceRecord);
838 if (outActivity != null) {
842 if (r.appTimeTracker == null && sourceRecord != null) {
843 // If the caller didn't specify an explicit time tracker, we want to continue
844 // tracking under any it has.
845 r.appTimeTracker = sourceRecord.appTimeTracker;
848 final ActivityStack stack = mSupervisor.mFocusedStack;
850 // If we are starting an activity that is not from the same uid as the currently resumed
851 // one, check whether app switches are allowed.
852 if (voiceSession == null && (stack.getResumedActivity() == null
853 || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
854 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
855 realCallingPid, realCallingUid, "Activity start")) {
856 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
857 sourceRecord, startFlags, stack, callerApp));
858 ActivityOptions.abort(checkedOptions);
859 return ActivityManager.START_SWITCHES_CANCELED;
863 if (mService.mDidAppSwitch) {
864 // This is the second allowed switch since we stopped switches,
865 // so now just generally allow switches. Use case: user presses
866 // home (switches disabled, switch to home, mDidAppSwitch now true);
867 // user taps a home icon (coming from home so allowed, we hit here
868 // and now allow anyone to switch again).
869 mService.mAppSwitchesAllowedTime = 0;
871 mService.mDidAppSwitch = true;
874 mController.doPendingActivityLaunches(false);
876 maybeLogActivityStart(callingUid, callingPackage, realCallingUid, intent, callerApp, r,
877 originatingPendingIntent);
879 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
880 true /* doResume */, checkedOptions, inTask, outActivity);
883 private void maybeLogActivityStart(int callingUid, String callingPackage, int realCallingUid,
884 Intent intent, ProcessRecord callerApp, ActivityRecord r,
885 PendingIntentRecord originatingPendingIntent) {
886 boolean callerAppHasForegroundActivity = (callerApp != null)
887 ? callerApp.foregroundActivities
889 if (!mService.isActivityStartsLoggingEnabled() || callerAppHasForegroundActivity
891 // skip logging in this case
896 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "logActivityStart");
897 final int callingUidProcState = mService.getUidStateLocked(callingUid);
898 final boolean callingUidHasAnyVisibleWindow =
899 mService.mWindowManager.isAnyWindowVisibleForUid(callingUid);
900 final int realCallingUidProcState = (callingUid == realCallingUid)
901 ? callingUidProcState
902 : mService.getUidStateLocked(realCallingUid);
903 final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
904 ? callingUidHasAnyVisibleWindow
905 : mService.mWindowManager.isAnyWindowVisibleForUid(realCallingUid);
906 final String targetPackage = r.packageName;
907 final int targetUid = (r.appInfo != null) ? r.appInfo.uid : -1;
908 final int targetUidProcState = mService.getUidStateLocked(targetUid);
909 final boolean targetUidHasAnyVisibleWindow = (targetUid != -1)
910 ? mService.mWindowManager.isAnyWindowVisibleForUid(targetUid)
912 final String targetWhitelistTag = (targetUid != -1)
913 ? mService.getPendingTempWhitelistTagForUidLocked(targetUid)
916 mSupervisor.getActivityMetricsLogger().logActivityStart(intent, callerApp, r,
917 callingUid, callingPackage, callingUidProcState,
918 callingUidHasAnyVisibleWindow,
919 realCallingUid, realCallingUidProcState,
920 realCallingUidHasAnyVisibleWindow,
921 targetUid, targetPackage, targetUidProcState,
922 targetUidHasAnyVisibleWindow, targetWhitelistTag,
923 (originatingPendingIntent != null));
925 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
930 * Creates a launch intent for the given auxiliary resolution data.
932 private @NonNull Intent createLaunchIntent(@Nullable AuxiliaryResolveInfo auxiliaryResponse,
933 Intent originalIntent, String callingPackage, Bundle verificationBundle,
934 String resolvedType, int userId) {
935 if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
936 // request phase two resolution
937 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
938 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
939 verificationBundle, userId);
941 return InstantAppResolver.buildEphemeralInstallerIntent(
943 InstantAppResolver.sanitizeIntent(originalIntent),
944 auxiliaryResponse == null ? null : auxiliaryResponse.failureIntent,
949 auxiliaryResponse == null ? null : auxiliaryResponse.installFailureActivity,
950 auxiliaryResponse == null ? null : auxiliaryResponse.token,
951 auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo,
952 auxiliaryResponse == null ? null : auxiliaryResponse.filters);
955 void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
956 if (ActivityManager.isStartResultFatalError(result)) {
960 // We're waiting for an activity launch to finish, but that activity simply
961 // brought another activity to front. We must also handle the case where the task is already
962 // in the front as a result of the trampoline activity being in the same task (it will be
963 // considered focused as the trampoline will be finished). Let startActivityMayWait() know
964 // about this, so it waits for the new activity to become visible instead.
965 mSupervisor.reportWaitingActivityLaunchedIfNeeded(r, result);
967 ActivityStack startedActivityStack = null;
968 final ActivityStack currentStack = r.getStack();
969 if (currentStack != null) {
970 startedActivityStack = currentStack;
971 } else if (mTargetStack != null) {
972 startedActivityStack = targetStack;
975 if (startedActivityStack == null) {
979 final int clearTaskFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK;
980 boolean clearedTask = (mLaunchFlags & clearTaskFlags) == clearTaskFlags
981 && mReuseTask != null;
982 if (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP || clearedTask) {
983 // The activity was already running so it wasn't started, but either brought to the
984 // front or the new intent was delivered to it since it was already in front. Notify
985 // anyone interested in this piece of information.
986 switch (startedActivityStack.getWindowingMode()) {
987 case WINDOWING_MODE_PINNED:
988 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
991 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
992 final ActivityStack homeStack = mSupervisor.mHomeStack;
993 if (homeStack != null && homeStack.shouldBeVisible(null /* starting */)) {
994 mService.mWindowManager.showRecentApps();
1001 private int startActivityMayWait(IApplicationThread caller, int callingUid,
1002 String callingPackage, Intent intent, String resolvedType,
1003 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1004 IBinder resultTo, String resultWho, int requestCode, int startFlags,
1005 ProfilerInfo profilerInfo, WaitResult outResult,
1006 Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
1007 int userId, TaskRecord inTask, String reason,
1008 boolean allowPendingRemoteAnimationRegistryLookup,
1009 PendingIntentRecord originatingPendingIntent) {
1010 // Refuse possible leaked file descriptors
1011 if (intent != null && intent.hasFileDescriptors()) {
1012 throw new IllegalArgumentException("File descriptors passed in Intent");
1014 mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
1015 boolean componentSpecified = intent.getComponent() != null;
1017 final int realCallingPid = Binder.getCallingPid();
1018 final int realCallingUid = Binder.getCallingUid();
1021 if (callingUid >= 0) {
1023 } else if (caller == null) {
1024 callingPid = realCallingPid;
1025 callingUid = realCallingUid;
1027 callingPid = callingUid = -1;
1030 // Save a copy in case ephemeral needs it
1031 final Intent ephemeralIntent = new Intent(intent);
1032 // Don't modify the client's object!
1033 intent = new Intent(intent);
1034 if (componentSpecified
1035 && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
1036 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
1037 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
1038 && mService.getPackageManagerInternalLocked()
1039 .isInstantAppInstallerComponent(intent.getComponent())) {
1040 // intercept intents targeted directly to the ephemeral installer the
1041 // ephemeral installer should never be started with a raw Intent; instead
1042 // adjust the intent so it looks like a "normal" instant app launch
1043 intent.setComponent(null /*component*/);
1044 componentSpecified = false;
1047 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
1049 computeResolveFilterUid(
1050 callingUid, realCallingUid, mRequest.filterCallingUid));
1051 if (rInfo == null) {
1052 UserInfo userInfo = mSupervisor.getUserInfo(userId);
1053 if (userInfo != null && userInfo.isManagedProfile()) {
1054 // Special case for managed profiles, if attempting to launch non-cryto aware
1055 // app in a locked managed profile from an unlocked parent allow it to resolve
1056 // as user will be sent via confirm credentials to unlock the profile.
1057 UserManager userManager = UserManager.get(mService.mContext);
1058 boolean profileLockedAndParentUnlockingOrUnlocked = false;
1059 long token = Binder.clearCallingIdentity();
1061 UserInfo parent = userManager.getProfileParent(userId);
1062 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
1063 && userManager.isUserUnlockingOrUnlocked(parent.id)
1064 && !userManager.isUserUnlockingOrUnlocked(userId);
1066 Binder.restoreCallingIdentity(token);
1068 if (profileLockedAndParentUnlockingOrUnlocked) {
1069 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
1070 PackageManager.MATCH_DIRECT_BOOT_AWARE
1071 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1072 computeResolveFilterUid(
1073 callingUid, realCallingUid, mRequest.filterCallingUid));
1077 // Collect information about the target of the Intent.
1078 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
1080 synchronized (mService) {
1081 final ActivityStack stack = mSupervisor.mFocusedStack;
1082 stack.mConfigWillChange = globalConfig != null
1083 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
1084 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1085 "Starting activity when config will change = " + stack.mConfigWillChange);
1087 final long origId = Binder.clearCallingIdentity();
1089 if (aInfo != null &&
1090 (aInfo.applicationInfo.privateFlags
1091 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 &&
1092 mService.mHasHeavyWeightFeature) {
1093 // This may be a heavy-weight process! Check to see if we already
1094 // have another, different heavy-weight process running.
1095 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
1096 final ProcessRecord heavy = mService.mHeavyWeightProcess;
1097 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
1098 || !heavy.processName.equals(aInfo.processName))) {
1099 int appCallingUid = callingUid;
1100 if (caller != null) {
1101 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
1102 if (callerApp != null) {
1103 appCallingUid = callerApp.info.uid;
1105 Slog.w(TAG, "Unable to find app for caller " + caller
1106 + " (pid=" + callingPid + ") when starting: "
1107 + intent.toString());
1108 SafeActivityOptions.abort(options);
1109 return ActivityManager.START_PERMISSION_DENIED;
1113 IIntentSender target = mService.getIntentSenderLocked(
1114 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
1115 appCallingUid, userId, null, null, 0, new Intent[] { intent },
1116 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
1117 | PendingIntent.FLAG_ONE_SHOT, null);
1119 Intent newIntent = new Intent();
1120 if (requestCode >= 0) {
1121 // Caller is requesting a result.
1122 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
1124 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
1125 new IntentSender(target));
1126 if (heavy.activities.size() > 0) {
1127 ActivityRecord hist = heavy.activities.get(0);
1128 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
1130 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
1131 hist.getTask().taskId);
1133 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
1135 newIntent.setFlags(intent.getFlags());
1136 newIntent.setClassName("android",
1137 HeavyWeightSwitcherActivity.class.getName());
1139 resolvedType = null;
1141 callingUid = Binder.getCallingUid();
1142 callingPid = Binder.getCallingPid();
1143 componentSpecified = true;
1144 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
1145 0 /* matchFlags */, computeResolveFilterUid(
1146 callingUid, realCallingUid, mRequest.filterCallingUid));
1147 aInfo = rInfo != null ? rInfo.activityInfo : null;
1148 if (aInfo != null) {
1149 aInfo = mService.getActivityInfoForUser(aInfo, userId);
1155 final ActivityRecord[] outRecord = new ActivityRecord[1];
1156 int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
1157 voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
1158 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
1159 ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
1160 allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);
1162 Binder.restoreCallingIdentity(origId);
1164 if (stack.mConfigWillChange) {
1165 // If the caller also wants to switch to a new configuration,
1166 // do so now. This allows a clean switch, as we are waiting
1167 // for the current activity to pause (so we will not destroy
1168 // it), and have not yet started the next activity.
1169 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
1170 "updateConfiguration()");
1171 stack.mConfigWillChange = false;
1172 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1173 "Updating to new configuration after starting activity.");
1174 mService.updateConfigurationLocked(globalConfig, null, false);
1177 // Notify ActivityMetricsLogger that the activity has launched. ActivityMetricsLogger
1178 // will then wait for the windows to be drawn and populate WaitResult.
1179 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
1180 if (outResult != null) {
1181 outResult.result = res;
1183 final ActivityRecord r = outRecord[0];
1186 case START_SUCCESS: {
1187 mSupervisor.mWaitingActivityLaunched.add(outResult);
1191 } catch (InterruptedException e) {
1193 } while (outResult.result != START_TASK_TO_FRONT
1194 && !outResult.timeout && outResult.who == null);
1195 if (outResult.result == START_TASK_TO_FRONT) {
1196 res = START_TASK_TO_FRONT;
1200 case START_DELIVERED_TO_TOP: {
1201 outResult.timeout = false;
1202 outResult.who = r.realActivity;
1203 outResult.totalTime = 0;
1206 case START_TASK_TO_FRONT: {
1207 // ActivityRecord may represent a different activity, but it should not be
1208 // in the resumed state.
1209 if (r.nowVisible && r.isState(RESUMED)) {
1210 outResult.timeout = false;
1211 outResult.who = r.realActivity;
1212 outResult.totalTime = 0;
1214 final long startTimeMs = SystemClock.uptimeMillis();
1215 mSupervisor.waitActivityVisible(r.realActivity, outResult, startTimeMs);
1216 // Note: the timeout variable is not currently not ever set.
1220 } catch (InterruptedException e) {
1222 } while (!outResult.timeout && outResult.who == null);
1234 * Compute the logical UID based on which the package manager would filter
1235 * app components i.e. based on which the instant app policy would be applied
1236 * because it is the logical calling UID.
1238 * @param customCallingUid The UID on whose behalf to make the call.
1239 * @param actualCallingUid The UID actually making the call.
1240 * @param filterCallingUid The UID to be used to filter for instant apps.
1241 * @return The logical UID making the call.
1243 static int computeResolveFilterUid(int customCallingUid, int actualCallingUid,
1244 int filterCallingUid) {
1245 return filterCallingUid != UserHandle.USER_NULL
1247 : (customCallingUid >= 0 ? customCallingUid : actualCallingUid);
1250 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
1251 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1252 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1253 ActivityRecord[] outActivity) {
1254 int result = START_CANCELED;
1256 mService.mWindowManager.deferSurfaceLayout();
1257 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
1258 startFlags, doResume, options, inTask, outActivity);
1260 // If we are not able to proceed, disassociate the activity from the task. Leaving an
1261 // activity in an incomplete state can lead to issues, such as performing operations
1262 // without a window container.
1263 final ActivityStack stack = mStartActivity.getStack();
1264 if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
1265 stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
1266 null /* intentResultData */, "startActivity", true /* oomAdj */);
1268 mService.mWindowManager.continueSurfaceLayout();
1271 postStartActivityProcessing(r, result, mTargetStack);
1276 // Note: This method should only be called from {@link startActivity}.
1277 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1278 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1279 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1280 ActivityRecord[] outActivity) {
1282 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1285 computeLaunchingTaskFlags();
1287 computeSourceStack();
1289 mIntent.setFlags(mLaunchFlags);
1291 ActivityRecord reusedActivity = getReusableIntentActivity();
1293 int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1294 int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1295 if (mOptions != null) {
1296 preferredWindowingMode = mOptions.getLaunchWindowingMode();
1297 preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1300 // windowing mode and preferred launch display values from {@link LaunchParams} take
1301 // priority over those specified in {@link ActivityOptions}.
1302 if (!mLaunchParams.isEmpty()) {
1303 if (mLaunchParams.hasPreferredDisplay()) {
1304 preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
1307 if (mLaunchParams.hasWindowingMode()) {
1308 preferredWindowingMode = mLaunchParams.mWindowingMode;
1312 if (reusedActivity != null) {
1313 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1314 // still needs to be a lock task mode violation since the task gets cleared out and
1315 // the device would otherwise leave the locked task.
1316 if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
1317 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1318 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1319 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1320 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1323 // True if we are clearing top and resetting of a standard (default) launch mode
1324 // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
1325 final boolean clearTopAndResetStandardLaunchMode =
1326 (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
1327 == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
1328 && mLaunchMode == LAUNCH_MULTIPLE;
1330 // If mStartActivity does not have a task associated with it, associate it with the
1331 // reused activity's task. Do not do so if we're clearing top and resetting for a
1332 // standard launchMode activity.
1333 if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
1334 mStartActivity.setTask(reusedActivity.getTask());
1337 if (reusedActivity.getTask().intent == null) {
1338 // This task was started because of movement of the activity based on affinity...
1339 // Now that we are actually launching it, we can assign the base intent.
1340 reusedActivity.getTask().setIntent(mStartActivity);
1343 // This code path leads to delivering a new intent, we want to make sure we schedule it
1344 // as the first operation, in case the activity will be resumed as a result of later
1346 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1347 || isDocumentLaunchesIntoExisting(mLaunchFlags)
1348 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1349 final TaskRecord task = reusedActivity.getTask();
1351 // In this situation we want to remove all activities from the task up to the one
1352 // being started. In most cases this means we are resetting the task to its initial
1354 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1357 // The above code can remove {@code reusedActivity} from the task, leading to the
1358 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1359 // task reference is needed in the call below to
1360 // {@link setTargetStackAndMoveToFrontIfNeeded}.
1361 if (reusedActivity.getTask() == null) {
1362 reusedActivity.setTask(task);
1366 if (top.frontOfTask) {
1367 // Activity aliases may mean we use different intents for the top activity,
1368 // so make sure the task now has the identity of the new intent.
1369 top.getTask().setIntent(mStartActivity);
1371 deliverNewIntent(top);
1375 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
1377 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
1379 final ActivityRecord outResult =
1380 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1382 // When there is a reused activity and the current result is a trampoline activity,
1383 // set the reused activity as the result.
1384 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1385 outActivity[0] = reusedActivity;
1388 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1389 // We don't need to start a new activity, and the client said not to do anything
1390 // if that is the case, so this is it! And for paranoia, make sure we have
1391 // correctly resumed the top activity.
1392 resumeTargetStackIfNeeded();
1393 return START_RETURN_INTENT_TO_CALLER;
1396 if (reusedActivity != null) {
1397 setTaskFromIntentActivity(reusedActivity);
1399 if (!mAddingToTask && mReuseTask == null) {
1400 // We didn't do anything... but it was needed (a.k.a., client don't use that
1401 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1403 resumeTargetStackIfNeeded();
1404 if (outActivity != null && outActivity.length > 0) {
1405 outActivity[0] = reusedActivity;
1408 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
1413 if (mStartActivity.packageName == null) {
1414 final ActivityStack sourceStack = mStartActivity.resultTo != null
1415 ? mStartActivity.resultTo.getStack() : null;
1416 if (sourceStack != null) {
1417 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1418 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1421 ActivityOptions.abort(mOptions);
1422 return START_CLASS_NOT_FOUND;
1425 // If the activity being launched is the same as the one currently at the top, then
1426 // we need to check if it should only be launched once.
1427 final ActivityStack topStack = mSupervisor.mFocusedStack;
1428 final ActivityRecord topFocused = topStack.getTopActivity();
1429 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1430 final boolean dontStart = top != null && mStartActivity.resultTo == null
1431 && top.realActivity.equals(mStartActivity.realActivity)
1432 && top.userId == mStartActivity.userId
1433 && top.app != null && top.app.thread != null
1434 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1435 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
1437 // For paranoia, make sure we have correctly resumed the top activity.
1438 topStack.mLastPausedActivity = null;
1440 mSupervisor.resumeFocusedStackTopActivityLocked();
1442 ActivityOptions.abort(mOptions);
1443 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1444 // We don't need to start a new activity, and the client said not to do
1445 // anything if that is the case, so this is it!
1446 return START_RETURN_INTENT_TO_CALLER;
1449 deliverNewIntent(top);
1451 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1452 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1453 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
1454 preferredLaunchDisplayId, topStack);
1456 return START_DELIVERED_TO_TOP;
1459 boolean newTask = false;
1460 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1461 ? mSourceRecord.getTask() : null;
1463 // Should this be considered a new task?
1464 int result = START_SUCCESS;
1465 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1466 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1468 result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
1469 } else if (mSourceRecord != null) {
1470 result = setTaskFromSourceRecord();
1471 } else if (mInTask != null) {
1472 result = setTaskFromInTask();
1474 // This not being started from an existing activity, and not part of a new task...
1475 // just put it in the top task, though these days this case should never happen.
1476 setTaskToCurrentTopOrCreateNewTask();
1478 if (result != START_SUCCESS) {
1482 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1483 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1484 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1485 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
1487 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1488 mStartActivity.getTask().taskId);
1490 ActivityStack.logStartActivity(
1491 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
1492 mTargetStack.mLastPausedActivity = null;
1494 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
1496 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1499 final ActivityRecord topTaskActivity =
1500 mStartActivity.getTask().topRunningActivityLocked();
1501 if (!mTargetStack.isFocusable()
1502 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1503 && mStartActivity != topTaskActivity)) {
1504 // If the activity is not focusable, we can't resume it, but still would like to
1505 // make sure it becomes visible as it starts (this will also trigger entry
1506 // animation). An example of this are PIP activities.
1507 // Also, we don't want to resume activities in a task that currently has an overlay
1508 // as the starting activity just needs to be in the visible paused state until the
1510 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1511 // Go ahead and tell window manager to execute app transition for this activity
1512 // since the app transition will not be triggered through the resume channel.
1513 mService.mWindowManager.executeAppTransition();
1515 // If the target stack was not previously focusable (previous top running activity
1516 // on that stack was not visible) then any prior calls to move the stack to the
1517 // will not update the focused stack. If starting the new activity now allows the
1518 // task stack to be focusable, then ensure that we now update the focused stack
1520 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1521 mTargetStack.moveToFront("startActivityUnchecked");
1523 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1526 } else if (mStartActivity != null) {
1527 mSupervisor.mRecentTasks.add(mStartActivity.getTask());
1529 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1531 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
1532 preferredLaunchDisplayId, mTargetStack);
1534 return START_SUCCESS;
1538 * Resets the {@link ActivityStarter} state.
1539 * @param clearRequest whether the request should be reset to default values.
1541 void reset(boolean clearRequest) {
1542 mStartActivity = null;
1547 mLaunchTaskBehind = false;
1549 mLaunchMode = INVALID_LAUNCH_MODE;
1551 mLaunchParams.reset();
1556 mSourceRecord = null;
1557 mPreferredDisplayId = INVALID_DISPLAY;
1560 mAddingToTask = false;
1563 mNewTaskInfo = null;
1564 mNewTaskIntent = null;
1565 mSourceStack = null;
1567 mTargetStack = null;
1568 mMovedToFront = false;
1569 mNoAnimation = false;
1570 mKeepCurTransition = false;
1571 mAvoidMoveToFront = false;
1573 mVoiceSession = null;
1574 mVoiceInteractor = null;
1576 mIntentDelivered = false;
1583 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1584 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1585 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1586 reset(false /* clearRequest */);
1591 mCallingUid = r.launchedFromUid;
1592 mSourceRecord = sourceRecord;
1593 mVoiceSession = voiceSession;
1594 mVoiceInteractor = voiceInteractor;
1596 mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
1598 mLaunchParams.reset();
1600 mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
1601 options, mLaunchParams);
1603 mLaunchMode = r.launchMode;
1605 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1606 r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
1607 LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
1608 mLaunchTaskBehind = r.mLaunchTaskBehind
1609 && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
1610 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1612 sendNewTaskResultRequestIfNeeded();
1614 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1615 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1618 // If we are actually going to launch in to a new task, there are some cases where
1619 // we further want to do multiple task.
1620 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1621 if (mLaunchTaskBehind
1622 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1623 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1627 // We'll invoke onUserLeaving before onPause only if the launching
1628 // activity did not explicitly state that this is an automated launch.
1629 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1630 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1631 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1633 // If the caller has asked not to resume at this point, we make note
1634 // of this in the record so that we can skip it when trying to find
1635 // the top running activity.
1636 mDoResume = doResume;
1637 if (!doResume || !r.okToShowLocked()) {
1638 r.delayedResume = true;
1642 if (mOptions != null) {
1643 if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1644 r.mTaskOverlay = true;
1645 if (!mOptions.canTaskOverlayResume()) {
1646 final TaskRecord task = mSupervisor.anyTaskForIdLocked(
1647 mOptions.getLaunchTaskId());
1648 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1649 if (top != null && !top.isState(RESUMED)) {
1651 // The caller specifies that we'd like to be avoided to be moved to the
1654 mAvoidMoveToFront = true;
1657 } else if (mOptions.getAvoidMoveToFront()) {
1659 mAvoidMoveToFront = true;
1663 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1666 // In some flows in to this function, we retrieve the task record and hold on to it
1667 // without a lock before calling back in to here... so the task at this point may
1668 // not actually be in recents. Check for that, and if it isn't in recents just
1669 // consider it invalid.
1670 if (inTask != null && !inTask.inRecents) {
1671 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1675 mStartFlags = startFlags;
1676 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1677 // is the same as the one making the call... or, as a special case, if we do not know
1678 // the caller then we count the current top activity as the caller.
1679 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1680 ActivityRecord checkedCaller = sourceRecord;
1681 if (checkedCaller == null) {
1682 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1685 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1686 // Caller is not the same as launcher, so always needed.
1687 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1691 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1694 private void sendNewTaskResultRequestIfNeeded() {
1695 final ActivityStack sourceStack = mStartActivity.resultTo != null
1696 ? mStartActivity.resultTo.getStack() : null;
1697 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1698 // For whatever reason this activity is being launched into a new task...
1699 // yet the caller has requested a result back. Well, that is pretty messed up,
1700 // so instead immediately send back a cancel and let the new task continue launched
1701 // as normal without a dependency on its originator.
1702 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1703 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1704 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1706 mStartActivity.resultTo = null;
1710 private void computeLaunchingTaskFlags() {
1711 // If the caller is not coming from another activity, but has given us an explicit task into
1712 // which they would like us to launch the new activity, then let's see about doing that.
1713 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
1714 final Intent baseIntent = mInTask.getBaseIntent();
1715 final ActivityRecord root = mInTask.getRootActivity();
1716 if (baseIntent == null) {
1717 ActivityOptions.abort(mOptions);
1718 throw new IllegalArgumentException("Launching into task without base intent: "
1722 // If this task is empty, then we are adding the first activity -- it
1723 // determines the root, and must be launching as a NEW_TASK.
1724 if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1725 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1726 ActivityOptions.abort(mOptions);
1727 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1728 + mStartActivity + " into different task " + mInTask);
1731 ActivityOptions.abort(mOptions);
1732 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1733 + " has root " + root + " but target is singleInstance/Task");
1737 // If task is empty, then adopt the interesting intent launch flags in to the
1738 // activity being started.
1740 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1741 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1742 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1743 | (baseIntent.getFlags() & flagsOfInterest);
1744 mIntent.setFlags(mLaunchFlags);
1745 mInTask.setIntent(mStartActivity);
1746 mAddingToTask = true;
1748 // If the task is not empty and the caller is asking to start it as the root of
1749 // a new task, then we don't actually want to start this on the task. We will
1750 // bring the task to the front, and possibly give it a new intent.
1751 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1752 mAddingToTask = false;
1755 mAddingToTask = true;
1758 mReuseTask = mInTask;
1761 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1762 // when in freeform workspace.
1763 // Also put noDisplay activities in the source task. These by itself can be placed
1764 // in any task/stack, however it could launch other activities like ResolverActivity,
1765 // and we want those to stay in the original task.
1766 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1767 && mSourceRecord.inFreeformWindowingMode()) {
1768 mAddingToTask = true;
1772 if (mInTask == null) {
1773 if (mSourceRecord == null) {
1774 // This activity is not being started from another... in this
1775 // case we -always- start a new task.
1776 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1777 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1778 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1779 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1781 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1782 // The original activity who is starting us is running as a single
1783 // instance... this new activity it is starting must go on its
1785 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1786 } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1787 // The activity being started is a single instance... it always
1788 // gets launched into its own task.
1789 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1794 private void computeSourceStack() {
1795 if (mSourceRecord == null) {
1796 mSourceStack = null;
1799 if (!mSourceRecord.finishing) {
1800 mSourceStack = mSourceRecord.getStack();
1804 // If the source is finishing, we can't further count it as our source. This is because the
1805 // task it is associated with may now be empty and on its way out, so we don't want to
1806 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1807 // a task for it. But save the task information so it can be used when creating the new task.
1808 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1809 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1810 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1811 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1812 mNewTaskInfo = mSourceRecord.info;
1814 // It is not guaranteed that the source record will have a task associated with it. For,
1815 // example, if this method is being called for processing a pending activity launch, it
1816 // is possible that the activity has been removed from the task after the launch was
1818 final TaskRecord sourceTask = mSourceRecord.getTask();
1819 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
1821 mSourceRecord = null;
1822 mSourceStack = null;
1826 * Decide whether the new activity should be inserted into an existing task. Returns null
1827 * if not or an ActivityRecord with the task into which the new activity should be added.
1829 private ActivityRecord getReusableIntentActivity() {
1830 // We may want to try to place the new activity in to an existing task. We always
1831 // do this if the target activity is singleTask or singleInstance; we will also do
1832 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1833 // us to still place it in a new task: multi task, always doc mode, or being asked to
1834 // launch this as a new task behind the current one.
1835 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1836 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1837 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
1838 // If bring to front is requested, and no result is requested and we have not been given
1839 // an explicit task to launch in to, and we can find a task that was started with this
1840 // same component, then instead of launching bring that one to the front.
1841 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1842 ActivityRecord intentActivity = null;
1843 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1844 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1845 intentActivity = task != null ? task.getTopActivity() : null;
1846 } else if (putIntoExistingTask) {
1847 if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
1848 // There can be one and only one instance of single instance activity in the
1849 // history, and it is always in its own unique task, so we do a special search.
1850 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1851 mStartActivity.isActivityTypeHome());
1852 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1853 // For the launch adjacent case we only want to put the activity in an existing
1854 // task if the activity already exists in the history.
1855 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1856 !(LAUNCH_SINGLE_TASK == mLaunchMode));
1858 // Otherwise find the best task to put the activity in.
1859 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
1862 return intentActivity;
1866 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1867 * then return the Vr mode's virtual display ID. If not, if the activity was started with
1868 * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
1869 * set, use that to launch the activity.
1871 private int getPreferedDisplayId(
1872 ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
1873 // Check if the Activity is a VR activity. If so, the activity should be launched in
1875 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1876 return DEFAULT_DISPLAY;
1879 // Get the virtual display id from ActivityManagerService.
1880 int displayId = mService.mVr2dDisplayId;
1881 if (displayId != INVALID_DISPLAY) {
1883 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1888 // If the caller requested a display, prefer that display.
1889 final int launchDisplayId =
1890 (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
1891 if (launchDisplayId != INVALID_DISPLAY) {
1892 return launchDisplayId;
1895 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1896 // If the activity has a displayId set explicitly, launch it on the same displayId.
1897 if (displayId != INVALID_DISPLAY) {
1900 return DEFAULT_DISPLAY;
1904 * Figure out which task and activity to bring to front when we have found an existing matching
1905 * activity record in history. May also clear the task if needed.
1906 * @param intentActivity Existing matching activity.
1907 * @return {@link ActivityRecord} brought to front.
1909 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1910 mTargetStack = intentActivity.getStack();
1911 mTargetStack.mLastPausedActivity = null;
1912 // If the target task is not in the front, then we need to bring it to the front...
1913 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1914 // the same behavior as if a new instance was being started, which means not bringing it
1915 // to the front if the caller is not itself in the front.
1916 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1917 ActivityRecord curTop = (focusStack == null)
1918 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1920 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1922 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
1923 && !mAvoidMoveToFront) {
1924 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1925 if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
1926 mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
1927 // We really do want to push this one into the user's face, right now.
1928 if (mLaunchTaskBehind && mSourceRecord != null) {
1929 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
1932 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1933 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1934 // So no point resuming any of the activities here, it just wastes one extra
1935 // resuming, plus enter AND exit transitions.
1936 // Here we only want to bring the target stack forward. Transition will be applied
1937 // to the new activity that's started after the old ones are gone.
1938 final boolean willClearTask =
1939 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1940 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1941 if (!willClearTask) {
1942 final ActivityStack launchStack = getLaunchStack(
1943 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1944 final TaskRecord intentTask = intentActivity.getTask();
1945 if (launchStack == null || launchStack == mTargetStack) {
1946 // We only want to move to the front, if we aren't going to launch on a
1947 // different stack. If we launch on a different stack, we will put the
1948 // task on top there.
1949 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1950 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1951 mMovedToFront = true;
1952 } else if (launchStack.inSplitScreenWindowingMode()) {
1953 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1954 // If we want to launch adjacent and mTargetStack is not the computed
1955 // launch stack - move task to top of computed stack.
1956 intentTask.reparent(launchStack, ON_TOP,
1957 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1960 // TODO: This should be reevaluated in MW v2.
1961 // We choose to move task to front instead of launching it adjacent
1962 // when specific stack was requested explicitly and it appeared to be
1963 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1964 mTargetStack.moveTaskToFrontLocked(intentTask,
1965 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
1966 "bringToFrontInsteadOfAdjacentLaunch");
1968 mMovedToFront = launchStack != launchStack.getDisplay()
1969 .getTopStackInWindowingMode(launchStack.getWindowingMode());
1970 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1971 // Target and computed stacks are on different displays and we've
1972 // found a matching task - move the existing instance to that display and
1973 // move it to front.
1974 intentActivity.getTask().reparent(launchStack, ON_TOP,
1975 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1976 "reparentToDisplay");
1977 mMovedToFront = true;
1978 } else if (launchStack.isActivityTypeHome()
1979 && !mTargetStack.isActivityTypeHome()) {
1980 // It is possible for the home activity to be in another stack initially.
1981 // For example, the activity may have been initially started with an intent
1982 // which placed it in the fullscreen stack. To ensure the proper handling of
1983 // the activity based on home stack assumptions, we must move it over.
1984 intentActivity.getTask().reparent(launchStack, ON_TOP,
1985 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1987 mMovedToFront = true;
1991 // We are moving a task to the front, use starting window to hide initial drawn
1993 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1994 true /* taskSwitch */);
1998 // Need to update mTargetStack because if task was moved out of it, the original stack may
2000 mTargetStack = intentActivity.getStack();
2001 if (!mMovedToFront && mDoResume) {
2002 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
2003 + " from " + intentActivity);
2004 mTargetStack.moveToFront("intentActivityFound");
2007 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
2008 WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
2010 // If the caller has requested that the target task be reset, then do so.
2011 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2012 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
2014 return intentActivity;
2017 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
2018 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
2019 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
2020 // The caller has requested to completely replace any existing task with its new
2021 // activity. Well that should not be too hard...
2022 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
2023 // removed from calling performClearTaskLocked (For example, if it is being brought out
2024 // of history or if it is finished immediately), thus disassociating the task. Also note
2025 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
2026 // launching another activity.
2027 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
2028 // already launching one.
2029 final TaskRecord task = intentActivity.getTask();
2030 task.performClearTaskLocked();
2032 mReuseTask.setIntent(mStartActivity);
2033 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
2034 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
2035 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
2038 // A special case: we need to start the activity because it is not currently
2039 // running, and the caller has asked to clear the current task to have this
2040 // activity at the top.
2041 mAddingToTask = true;
2043 // We are no longer placing the activity in the task we previously thought we were.
2044 mStartActivity.setTask(null);
2045 // Now pretend like this activity is being started by the top of its task, so it
2046 // is put in the right place.
2047 mSourceRecord = intentActivity;
2048 final TaskRecord task = mSourceRecord.getTask();
2049 if (task != null && task.getStack() == null) {
2050 // Target stack got cleared when we all activities were removed above.
2051 // Go ahead and reset it.
2052 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
2053 mLaunchFlags, mOptions);
2054 mTargetStack.addTask(task,
2055 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
2058 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
2059 // In this case the top activity on the task is the same as the one being launched,
2060 // so we take that as a request to bring the task to the foreground. If the top
2061 // activity in the task is the root activity, deliver this new intent to it if it
2063 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
2064 || LAUNCH_SINGLE_TOP == mLaunchMode)
2065 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
2066 if (intentActivity.frontOfTask) {
2067 intentActivity.getTask().setIntent(mStartActivity);
2069 deliverNewIntent(intentActivity);
2070 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
2071 // In this case we are launching the root activity of the task, but with a
2072 // different intent. We should start a new instance on top.
2073 mAddingToTask = true;
2074 mSourceRecord = intentActivity;
2076 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
2077 // In this case an activity is being launched in to an existing task, without
2078 // resetting that task. This is typically the situation of launching an activity
2079 // from a notification or shortcut. We want to place the new activity on top of the
2081 mAddingToTask = true;
2082 mSourceRecord = intentActivity;
2083 } else if (!intentActivity.getTask().rootWasReset) {
2084 // In this case we are launching into an existing task that has not yet been started
2085 // from its front door. The current task has been brought to the front. Ideally,
2086 // we'd probably like to place this new task at the bottom of its stack, but that's
2087 // a little hard to do with the current organization of the code so for now we'll
2089 intentActivity.getTask().setIntent(mStartActivity);
2093 private void resumeTargetStackIfNeeded() {
2095 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
2097 ActivityOptions.abort(mOptions);
2099 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
2102 private int setTaskFromReuseOrCreateNewTask(
2103 TaskRecord taskToAffiliate, ActivityStack topStack) {
2104 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
2106 // Do no move the target stack to front yet, as we might bail if
2107 // isLockTaskModeViolation fails below.
2109 if (mReuseTask == null) {
2110 final TaskRecord task = mTargetStack.createTaskRecord(
2111 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
2112 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
2113 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
2114 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
2116 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
2117 updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
2119 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2120 + " in new task " + mStartActivity.getTask());
2122 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
2125 if (taskToAffiliate != null) {
2126 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
2129 if (mService.getLockTaskController().isLockTaskModeViolation(mStartActivity.getTask())) {
2130 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2131 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2135 mTargetStack.moveToFront("reuseOrNewTask");
2137 return START_SUCCESS;
2140 private void deliverNewIntent(ActivityRecord activity) {
2141 if (mIntentDelivered) {
2145 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
2146 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
2147 mStartActivity.launchedFromPackage);
2148 mIntentDelivered = true;
2151 private int setTaskFromSourceRecord() {
2152 if (mService.getLockTaskController().isLockTaskModeViolation(mSourceRecord.getTask())) {
2153 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2154 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2157 final TaskRecord sourceTask = mSourceRecord.getTask();
2158 final ActivityStack sourceStack = mSourceRecord.getStack();
2159 // We only want to allow changing stack in two cases:
2160 // 1. If the target task is not the top one. Otherwise we would move the launching task to
2161 // the other side, rather than show two side by side.
2162 // 2. If activity is not allowed on target display.
2163 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
2164 : sourceStack.mDisplayId;
2165 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
2166 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
2167 if (moveStackAllowed) {
2168 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
2170 // If target stack is not found now - we can't just rely on the source stack, as it may
2171 // be not suitable. Let's check other displays.
2172 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
2173 // Can't use target display, lets find a stack on the source display.
2174 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
2175 sourceStack.mDisplayId, mStartActivity);
2177 if (mTargetStack == null) {
2178 // There are no suitable stacks on the target and source display(s). Look on all
2180 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
2181 mStartActivity, -1 /* currentFocus */);
2185 if (mTargetStack == null) {
2186 mTargetStack = sourceStack;
2187 } else if (mTargetStack != sourceStack) {
2188 sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
2189 DEFER_RESUME, "launchToSide");
2192 final TaskRecord topTask = mTargetStack.topTask();
2193 if (topTask != sourceTask && !mAvoidMoveToFront) {
2194 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
2195 mStartActivity.appTimeTracker, "sourceTaskToFront");
2196 } else if (mDoResume) {
2197 mTargetStack.moveToFront("sourceStackToFront");
2200 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2201 // In this case, we are adding the activity to an existing task, but the caller has
2202 // asked to clear that task if the activity is already running.
2203 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
2204 mKeepCurTransition = true;
2206 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
2207 deliverNewIntent(top);
2208 // For paranoia, make sure we have correctly resumed the top activity.
2209 mTargetStack.mLastPausedActivity = null;
2211 mSupervisor.resumeFocusedStackTopActivityLocked();
2213 ActivityOptions.abort(mOptions);
2214 return START_DELIVERED_TO_TOP;
2216 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
2217 // In this case, we are launching an activity in our own task that may already be
2218 // running somewhere in the history, and we want to shuffle it to the front of the
2220 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
2222 final TaskRecord task = top.getTask();
2223 task.moveActivityToFrontLocked(top);
2224 top.updateOptionsLocked(mOptions);
2225 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
2226 deliverNewIntent(top);
2227 mTargetStack.mLastPausedActivity = null;
2229 mSupervisor.resumeFocusedStackTopActivityLocked();
2231 return START_DELIVERED_TO_TOP;
2235 // An existing activity is starting this new activity, so we want to keep the new one in
2236 // the same task as the one that is starting it.
2237 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
2238 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2239 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
2240 return START_SUCCESS;
2243 private int setTaskFromInTask() {
2244 // The caller is asking that the new activity be started in an explicit
2245 // task it has provided to us.
2246 if (mService.getLockTaskController().isLockTaskModeViolation(mInTask)) {
2247 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2248 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2251 mTargetStack = mInTask.getStack();
2253 // Check whether we should actually launch the new activity in to the task,
2254 // or just reuse the current activity on top.
2255 ActivityRecord top = mInTask.getTopActivity();
2256 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
2257 && top.userId == mStartActivity.userId) {
2258 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
2259 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
2260 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
2261 mStartActivity.appTimeTracker, "inTaskToFront");
2262 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
2263 // We don't need to start a new activity, and the client said not to do
2264 // anything if that is the case, so this is it!
2265 return START_RETURN_INTENT_TO_CALLER;
2267 deliverNewIntent(top);
2268 return START_DELIVERED_TO_TOP;
2272 if (!mAddingToTask) {
2273 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
2274 mStartActivity.appTimeTracker, "inTaskToFront");
2275 // We don't actually want to have this activity added to the task, so just
2276 // stop here but still tell the caller that we consumed the intent.
2277 ActivityOptions.abort(mOptions);
2278 return START_TASK_TO_FRONT;
2281 if (!mLaunchParams.mBounds.isEmpty()) {
2282 // TODO: Shouldn't we already know what stack to use by the time we get here?
2283 ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
2284 if (stack != mInTask.getStack()) {
2285 mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
2286 DEFER_RESUME, "inTaskToFront");
2287 mTargetStack = mInTask.getStack();
2290 updateBounds(mInTask, mLaunchParams.mBounds);
2293 mTargetStack.moveTaskToFrontLocked(
2294 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
2296 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
2297 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2298 + " in explicit task " + mStartActivity.getTask());
2300 return START_SUCCESS;
2304 void updateBounds(TaskRecord task, Rect bounds) {
2305 if (bounds.isEmpty()) {
2309 final ActivityStack stack = task.getStack();
2310 if (stack != null && stack.resizeStackWithLaunchBounds()) {
2311 mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
2313 task.updateOverrideConfiguration(bounds);
2317 private void setTaskToCurrentTopOrCreateNewTask() {
2318 mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
2320 mTargetStack.moveToFront("addingToTopTask");
2322 final ActivityRecord prev = mTargetStack.getTopActivity();
2323 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
2324 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
2325 mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
2326 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2327 mTargetStack.positionChildWindowContainerAtTop(task);
2328 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
2329 + " in new guessed " + mStartActivity.getTask());
2332 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
2333 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
2334 parent.addActivityToTop(mStartActivity);
2336 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2340 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2341 boolean launchSingleTask, int launchFlags) {
2342 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2343 (launchSingleInstance || launchSingleTask)) {
2344 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2345 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2346 "\"singleInstance\" or \"singleTask\"");
2348 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2350 switch (r.info.documentLaunchMode) {
2351 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2353 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2354 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2356 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2357 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2359 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2360 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2367 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
2368 ActivityOptions aOptions) {
2369 final TaskRecord task = r.getTask();
2370 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
2371 if (stack != null) {
2375 final ActivityStack currentStack = task != null ? task.getStack() : null;
2376 if (currentStack != null) {
2377 if (mSupervisor.mFocusedStack != currentStack) {
2378 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2379 "computeStackFocus: Setting " + "focused stack to r=" + r
2382 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2383 "computeStackFocus: Focused stack already="
2384 + mSupervisor.mFocusedStack);
2386 return currentStack;
2389 if (canLaunchIntoFocusedStack(r, newTask)) {
2390 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2391 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2392 return mSupervisor.mFocusedStack;
2395 if (mPreferredDisplayId != DEFAULT_DISPLAY) {
2396 // Try to put the activity in a stack on a secondary display.
2397 stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
2398 if (stack == null) {
2399 // If source display is not suitable - look for topmost valid stack in the system.
2400 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2401 "computeStackFocus: Can't launch on mPreferredDisplayId="
2402 + mPreferredDisplayId + ", looking on all displays.");
2403 stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
2406 if (stack == null) {
2407 // We first try to put the task in the first dynamic stack on home display.
2408 final ActivityDisplay display = mSupervisor.getDefaultDisplay();
2409 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2410 stack = display.getChildAt(stackNdx);
2411 if (!stack.isOnHomeDisplay()) {
2412 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2413 "computeStackFocus: Setting focused stack=" + stack);
2417 // If there is no suitable dynamic stack then we figure out which static stack to use.
2418 stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
2420 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2421 + r + " stackId=" + stack.mStackId);
2425 /** Check if provided activity record can launch in currently focused stack. */
2426 // TODO: This method can probably be consolidated into getLaunchStack() below.
2427 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
2428 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2429 final boolean canUseFocusedStack;
2430 if (focusedStack.isActivityTypeAssistant()) {
2431 canUseFocusedStack = r.isActivityTypeAssistant();
2433 switch (focusedStack.getWindowingMode()) {
2434 case WINDOWING_MODE_FULLSCREEN:
2435 // The fullscreen stack can contain any task regardless of if the task is
2436 // resizeable or not. So, we let the task go in the fullscreen task if it is the
2438 canUseFocusedStack = true;
2440 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
2441 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
2442 // Any activity which supports split screen can go in the docked stack.
2443 canUseFocusedStack = r.supportsSplitScreenWindowingMode();
2445 case WINDOWING_MODE_FREEFORM:
2446 // Any activity which supports freeform can go in the freeform stack.
2447 canUseFocusedStack = r.supportsFreeform();
2450 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2452 canUseFocusedStack = !focusedStack.isOnHomeDisplay()
2453 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2456 return canUseFocusedStack && !newTask
2457 // Using the focus stack isn't important enough to override the preferred display.
2458 && (mPreferredDisplayId == focusedStack.mDisplayId);
2461 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
2462 ActivityOptions aOptions) {
2463 // We are reusing a task, keep the stack!
2464 if (mReuseTask != null) {
2465 return mReuseTask.getStack();
2468 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2469 || mPreferredDisplayId != DEFAULT_DISPLAY) {
2470 // We don't pass in the default display id into the get launch stack call so it can do a
2472 final int candidateDisplay =
2473 mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
2474 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, candidateDisplay);
2476 // Otherwise handle adjacent launch.
2478 // The parent activity doesn't want to launch the activity on top of itself, but
2479 // instead tries to put it onto other side in side-by-side mode.
2480 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
2482 if (parentStack != mSupervisor.mFocusedStack) {
2483 // If task's parent stack is not focused - use it during adjacent launch.
2486 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2487 // If task is already on top of focused stack - use it. We don't want to move the
2488 // existing focused task to adjacent stack, just deliver new intent in this case.
2489 return mSupervisor.mFocusedStack;
2492 if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
2493 // If parent was in docked stack, the natural place to launch another activity
2494 // will be fullscreen, so it can appear alongside the docked window.
2495 final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
2496 return parentStack.getDisplay().getOrCreateStack(
2497 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
2499 // If the parent is not in the docked stack, we check if there is docked window
2500 // and if yes, we will launch into that stack. If not, we just put the new
2501 // activity into parent's stack, because we can't find a better place.
2502 final ActivityStack dockedStack =
2503 mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
2504 if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
2505 // There is a docked stack, but it isn't visible, so we can't launch into that.
2506 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
2514 private boolean isLaunchModeOneOf(int mode1, int mode2) {
2515 return mode1 == mLaunchMode || mode2 == mLaunchMode;
2518 static boolean isDocumentLaunchesIntoExisting(int flags) {
2519 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2520 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2523 ActivityStarter setIntent(Intent intent) {
2524 mRequest.intent = intent;
2529 Intent getIntent() {
2530 return mRequest.intent;
2533 ActivityStarter setReason(String reason) {
2534 mRequest.reason = reason;
2538 ActivityStarter setCaller(IApplicationThread caller) {
2539 mRequest.caller = caller;
2543 ActivityStarter setEphemeralIntent(Intent intent) {
2544 mRequest.ephemeralIntent = intent;
2549 ActivityStarter setResolvedType(String type) {
2550 mRequest.resolvedType = type;
2554 ActivityStarter setActivityInfo(ActivityInfo info) {
2555 mRequest.activityInfo = info;
2559 ActivityStarter setResolveInfo(ResolveInfo info) {
2560 mRequest.resolveInfo = info;
2564 ActivityStarter setVoiceSession(IVoiceInteractionSession voiceSession) {
2565 mRequest.voiceSession = voiceSession;
2569 ActivityStarter setVoiceInteractor(IVoiceInteractor voiceInteractor) {
2570 mRequest.voiceInteractor = voiceInteractor;
2574 ActivityStarter setResultTo(IBinder resultTo) {
2575 mRequest.resultTo = resultTo;
2579 ActivityStarter setResultWho(String resultWho) {
2580 mRequest.resultWho = resultWho;
2584 ActivityStarter setRequestCode(int requestCode) {
2585 mRequest.requestCode = requestCode;
2589 ActivityStarter setCallingPid(int pid) {
2590 mRequest.callingPid = pid;
2594 ActivityStarter setCallingUid(int uid) {
2595 mRequest.callingUid = uid;
2599 ActivityStarter setCallingPackage(String callingPackage) {
2600 mRequest.callingPackage = callingPackage;
2604 ActivityStarter setRealCallingPid(int pid) {
2605 mRequest.realCallingPid = pid;
2609 ActivityStarter setRealCallingUid(int uid) {
2610 mRequest.realCallingUid = uid;
2614 ActivityStarter setStartFlags(int startFlags) {
2615 mRequest.startFlags = startFlags;
2619 ActivityStarter setActivityOptions(SafeActivityOptions options) {
2620 mRequest.activityOptions = options;
2624 ActivityStarter setActivityOptions(Bundle bOptions) {
2625 return setActivityOptions(SafeActivityOptions.fromBundle(bOptions));
2628 ActivityStarter setIgnoreTargetSecurity(boolean ignoreTargetSecurity) {
2629 mRequest.ignoreTargetSecurity = ignoreTargetSecurity;
2633 ActivityStarter setFilterCallingUid(int filterCallingUid) {
2634 mRequest.filterCallingUid = filterCallingUid;
2638 ActivityStarter setComponentSpecified(boolean componentSpecified) {
2639 mRequest.componentSpecified = componentSpecified;
2643 ActivityStarter setOutActivity(ActivityRecord[] outActivity) {
2644 mRequest.outActivity = outActivity;
2648 ActivityStarter setInTask(TaskRecord inTask) {
2649 mRequest.inTask = inTask;
2653 ActivityStarter setWaitResult(WaitResult result) {
2654 mRequest.waitResult = result;
2658 ActivityStarter setProfilerInfo(ProfilerInfo info) {
2659 mRequest.profilerInfo = info;
2663 ActivityStarter setGlobalConfiguration(Configuration config) {
2664 mRequest.globalConfig = config;
2668 ActivityStarter setUserId(int userId) {
2669 mRequest.userId = userId;
2673 ActivityStarter setMayWait(int userId) {
2674 mRequest.mayWait = true;
2675 mRequest.userId = userId;
2680 ActivityStarter setAllowPendingRemoteAnimationRegistryLookup(boolean allowLookup) {
2681 mRequest.allowPendingRemoteAnimationRegistryLookup = allowLookup;
2685 ActivityStarter setOriginatingPendingIntent(PendingIntentRecord originatingPendingIntent) {
2686 mRequest.originatingPendingIntent = originatingPendingIntent;
2690 void dump(PrintWriter pw, String prefix) {
2691 prefix = prefix + " ";
2693 pw.print("mCurrentUser=");
2694 pw.println(mSupervisor.mCurrentUser);
2696 pw.print("mLastStartReason=");
2697 pw.println(mLastStartReason);
2699 pw.print("mLastStartActivityTimeMs=");
2700 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2702 pw.print("mLastStartActivityResult=");
2703 pw.println(mLastStartActivityResult);
2704 ActivityRecord r = mLastStartActivityRecord[0];
2707 pw.println("mLastStartActivityRecord:");
2708 r.dump(pw, prefix + " ");
2710 if (mStartActivity != null) {
2712 pw.println("mStartActivity:");
2713 mStartActivity.dump(pw, prefix + " ");
2715 if (mIntent != null) {
2717 pw.print("mIntent=");
2718 pw.println(mIntent);
2720 if (mOptions != null) {
2722 pw.print("mOptions=");
2723 pw.println(mOptions);
2726 pw.print("mLaunchSingleTop=");
2727 pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
2728 pw.print(" mLaunchSingleInstance=");
2729 pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
2730 pw.print(" mLaunchSingleTask=");
2731 pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
2733 pw.print("mLaunchFlags=0x");
2734 pw.print(Integer.toHexString(mLaunchFlags));
2735 pw.print(" mDoResume=");
2736 pw.print(mDoResume);
2737 pw.print(" mAddingToTask=");
2738 pw.println(mAddingToTask);