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_CLASS_NOT_FOUND;
21 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
22 import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
23 import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
24 import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
25 import static android.app.ActivityManager.START_SUCCESS;
26 import static android.app.ActivityManager.START_TASK_TO_FRONT;
27 import static android.app.ActivityManager.StackId;
28 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
29 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
30 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
31 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
32 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
33 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
34 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
35 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
36 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
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.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
49 import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
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 com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
54 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
55 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
56 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
57 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
58 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
59 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
60 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
61 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
62 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
63 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
64 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
65 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
66 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
67 import static com.android.server.am.ActivityManagerService.ANIMATE;
68 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
69 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
70 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
71 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
72 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
73 import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
74 import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
75 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
76 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
77 import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
78 import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
80 import android.app.ActivityManager;
81 import android.app.ActivityOptions;
82 import android.app.AppGlobals;
83 import android.app.IActivityContainer;
84 import android.app.IActivityManager;
85 import android.app.IApplicationThread;
86 import android.app.KeyguardManager;
87 import android.app.PendingIntent;
88 import android.app.ProfilerInfo;
89 import android.content.ComponentName;
90 import android.content.Context;
91 import android.content.IIntentSender;
92 import android.content.Intent;
93 import android.content.IntentSender;
94 import android.content.pm.ActivityInfo;
95 import android.content.pm.ApplicationInfo;
96 import android.content.pm.PackageManager;
97 import android.content.pm.ResolveInfo;
98 import android.content.pm.UserInfo;
99 import android.content.res.Configuration;
100 import android.graphics.Rect;
101 import android.os.Binder;
102 import android.os.Build;
103 import android.os.Bundle;
104 import android.os.IBinder;
105 import android.os.PowerManagerInternal;
106 import android.os.Process;
107 import android.os.RemoteException;
108 import android.os.SystemClock;
109 import android.os.UserHandle;
110 import android.os.UserManager;
111 import android.service.voice.IVoiceInteractionSession;
112 import android.util.EventLog;
113 import android.util.Slog;
114 import android.view.Display;
116 import com.android.internal.app.HeavyWeightSwitcherActivity;
117 import com.android.internal.app.IVoiceInteractor;
118 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
119 import com.android.server.wm.WindowManagerService;
121 import java.util.ArrayList;
124 * Controller for interpreting how and then launching activities.
126 * This class collects all the logic for determining how an intent and flags should be turned into
127 * an activity and associated task and stack.
129 class ActivityStarter {
130 public static final int PID_NULL = 0;
132 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
133 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
134 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
135 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
136 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
138 // TODO b/30204367 remove when the platform fully supports ephemeral applications
139 private static final boolean USE_DEFAULT_EPHEMERAL_LAUNCHER = false;
141 private final ActivityManagerService mService;
142 private final ActivityStackSupervisor mSupervisor;
143 private ActivityStartInterceptor mInterceptor;
144 private WindowManagerService mWindowManager;
146 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
148 // Share state variable among methods when starting an activity.
149 private ActivityRecord mStartActivity;
150 private ActivityRecord mReusedActivity;
151 private Intent mIntent;
152 private int mCallingUid;
153 private ActivityOptions mOptions;
155 private boolean mLaunchSingleTop;
156 private boolean mLaunchSingleInstance;
157 private boolean mLaunchSingleTask;
158 private boolean mLaunchTaskBehind;
159 private int mLaunchFlags;
161 private Rect mLaunchBounds;
163 private ActivityRecord mNotTop;
164 private boolean mDoResume;
165 private int mStartFlags;
166 private ActivityRecord mSourceRecord;
168 private TaskRecord mInTask;
169 private boolean mAddingToTask;
170 private TaskRecord mReuseTask;
172 private ActivityInfo mNewTaskInfo;
173 private Intent mNewTaskIntent;
174 private ActivityStack mSourceStack;
175 private ActivityStack mTargetStack;
176 // Indicates that we moved other task and are going to put something on top soon, so
177 // we don't want to show it redundantly or accidentally change what's shown below.
178 private boolean mMovedOtherTask;
179 private boolean mMovedToFront;
180 private boolean mNoAnimation;
181 private boolean mKeepCurTransition;
182 private boolean mAvoidMoveToFront;
183 private boolean mPowerHintSent;
185 private IVoiceInteractionSession mVoiceSession;
186 private IVoiceInteractor mVoiceInteractor;
188 private void reset() {
189 mStartActivity = null;
194 mLaunchSingleTop = false;
195 mLaunchSingleInstance = false;
196 mLaunchSingleTask = false;
197 mLaunchTaskBehind = false;
200 mLaunchBounds = null;
205 mSourceRecord = null;
208 mAddingToTask = false;
212 mNewTaskIntent = null;
216 mMovedOtherTask = false;
217 mMovedToFront = false;
218 mNoAnimation = false;
219 mKeepCurTransition = false;
220 mAvoidMoveToFront = false;
222 mVoiceSession = null;
223 mVoiceInteractor = null;
226 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
228 mSupervisor = supervisor;
229 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
232 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
233 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
234 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
235 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
236 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
237 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
238 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
240 int err = ActivityManager.START_SUCCESS;
242 ProcessRecord callerApp = null;
243 if (caller != null) {
244 callerApp = mService.getRecordForAppLocked(caller);
245 if (callerApp != null) {
246 callingPid = callerApp.pid;
247 callingUid = callerApp.info.uid;
249 Slog.w(TAG, "Unable to find app for caller " + caller
250 + " (pid=" + callingPid + ") when starting: "
251 + intent.toString());
252 err = ActivityManager.START_PERMISSION_DENIED;
256 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
258 if (err == ActivityManager.START_SUCCESS) {
259 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
260 + "} from uid " + callingUid
261 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
262 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
263 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
264 container.mActivityDisplay.mDisplayId)));
267 ActivityRecord sourceRecord = null;
268 ActivityRecord resultRecord = null;
269 if (resultTo != null) {
270 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
271 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
272 "Will send result to " + resultTo + " " + sourceRecord);
273 if (sourceRecord != null) {
274 if (requestCode >= 0 && !sourceRecord.finishing) {
275 resultRecord = sourceRecord;
280 final int launchFlags = intent.getFlags();
282 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
283 // Transfer the result target from the source activity to the new
284 // one being started, including any failures.
285 if (requestCode >= 0) {
286 ActivityOptions.abort(options);
287 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
289 resultRecord = sourceRecord.resultTo;
290 if (resultRecord != null && !resultRecord.isInStackLocked()) {
293 resultWho = sourceRecord.resultWho;
294 requestCode = sourceRecord.requestCode;
295 sourceRecord.resultTo = null;
296 if (resultRecord != null) {
297 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
299 if (sourceRecord.launchedFromUid == callingUid) {
300 // The new activity is being launched from the same uid as the previous
301 // activity in the flow, and asking to forward its result back to the
302 // previous. In this case the activity is serving as a trampoline between
303 // the two, so we also want to update its launchedFromPackage to be the
304 // same as the previous activity. Note that this is safe, since we know
305 // these two packages come from the same uid; the caller could just as
306 // well have supplied that same package name itself. This specifially
307 // deals with the case of an intent picker/chooser being launched in the app
308 // flow to redirect to an activity picked by the user, where we want the final
309 // activity to consider it to have been launched by the previous app activity.
310 callingPackage = sourceRecord.launchedFromPackage;
314 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
315 // We couldn't find a class that can handle the given Intent.
316 // That's the end of that!
317 err = ActivityManager.START_INTENT_NOT_RESOLVED;
320 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
321 // We couldn't find the specific class specified in the Intent.
322 // Also the end of the line.
323 err = ActivityManager.START_CLASS_NOT_FOUND;
326 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
327 && sourceRecord.task.voiceSession != null) {
328 // If this activity is being launched as part of a voice session, we need
329 // to ensure that it is safe to do so. If the upcoming activity will also
330 // be part of the voice session, we can only launch it if it has explicitly
331 // said it supports the VOICE category, or it is a part of the calling app.
332 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
333 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
335 intent.addCategory(Intent.CATEGORY_VOICE);
336 if (!AppGlobals.getPackageManager().activitySupportsIntent(
337 intent.getComponent(), intent, resolvedType)) {
339 "Activity being started in current voice task does not support voice: "
341 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
343 } catch (RemoteException e) {
344 Slog.w(TAG, "Failure checking voice capabilities", e);
345 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
350 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
351 // If the caller is starting a new voice session, just make sure the target
352 // is actually allowing it to run this way.
354 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
355 intent, resolvedType)) {
357 "Activity being started in new voice task does not support: "
359 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
361 } catch (RemoteException e) {
362 Slog.w(TAG, "Failure checking voice capabilities", e);
363 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
367 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
369 if (err != START_SUCCESS) {
370 if (resultRecord != null) {
371 resultStack.sendActivityResultLocked(
372 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
374 ActivityOptions.abort(options);
378 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
379 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
380 resultRecord, resultStack, options);
381 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
382 callingPid, resolvedType, aInfo.applicationInfo);
384 if (mService.mController != null) {
386 // The Intent we give to the watcher has the extra data
387 // stripped off, since it can contain private information.
388 Intent watchIntent = intent.cloneFilter();
389 abort |= !mService.mController.activityStarting(watchIntent,
390 aInfo.applicationInfo.packageName);
391 } catch (RemoteException e) {
392 mService.mController = null;
396 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
397 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
399 intent = mInterceptor.mIntent;
400 rInfo = mInterceptor.mRInfo;
401 aInfo = mInterceptor.mAInfo;
402 resolvedType = mInterceptor.mResolvedType;
403 inTask = mInterceptor.mInTask;
404 callingPid = mInterceptor.mCallingPid;
405 callingUid = mInterceptor.mCallingUid;
406 options = mInterceptor.mActivityOptions;
408 if (resultRecord != null) {
409 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
410 RESULT_CANCELED, null);
412 // We pretend to the caller that it was really started, but
413 // they will just get a cancel result.
414 ActivityOptions.abort(options);
415 return START_SUCCESS;
418 // If permissions need a review before any of the app components can run, we
419 // launch the review activity and pass a pending intent to start the activity
420 // we are to launching now after the review is completed.
421 if ((mService.mPermissionReviewRequired
422 || Build.PERMISSIONS_REVIEW_REQUIRED) && aInfo != null) {
423 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
424 aInfo.packageName, userId)) {
425 IIntentSender target = mService.getIntentSenderLocked(
426 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
427 callingUid, userId, null, null, 0, new Intent[]{intent},
428 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
429 | PendingIntent.FLAG_ONE_SHOT, null);
431 final int flags = intent.getFlags();
432 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
433 newIntent.setFlags(flags
434 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
435 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
436 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
437 if (resultRecord != null) {
438 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
443 callingUid = realCallingUid;
444 callingPid = realCallingPid;
446 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
447 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
448 null /*profilerInfo*/);
450 if (DEBUG_PERMISSIONS_REVIEW) {
451 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
452 true, false) + "} from uid " + callingUid + " on display "
453 + (container == null ? (mSupervisor.mFocusedStack == null ?
454 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
455 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
456 container.mActivityDisplay.mDisplayId)));
461 // If we have an ephemeral app, abort the process of launching the resolved intent.
462 // Instead, launch the ephemeral installer. Once the installer is finished, it
463 // starts either the intent we resolved here [on install error] or the ephemeral
464 // app [on install success].
465 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
466 intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
467 rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
470 callingUid = realCallingUid;
471 callingPid = realCallingPid;
473 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
476 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
477 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
478 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
479 options, sourceRecord);
480 if (outActivity != null) {
484 if (r.appTimeTracker == null && sourceRecord != null) {
485 // If the caller didn't specify an explicit time tracker, we want to continue
486 // tracking under any it has.
487 r.appTimeTracker = sourceRecord.appTimeTracker;
490 final ActivityStack stack = mSupervisor.mFocusedStack;
491 if (voiceSession == null && (stack.mResumedActivity == null
492 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
493 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
494 realCallingPid, realCallingUid, "Activity start")) {
495 PendingActivityLaunch pal = new PendingActivityLaunch(r,
496 sourceRecord, startFlags, stack, callerApp);
497 mPendingActivityLaunches.add(pal);
498 ActivityOptions.abort(options);
499 return ActivityManager.START_SWITCHES_CANCELED;
503 if (mService.mDidAppSwitch) {
504 // This is the second allowed switch since we stopped switches,
505 // so now just generally allow switches. Use case: user presses
506 // home (switches disabled, switch to home, mDidAppSwitch now true);
507 // user taps a home icon (coming from home so allowed, we hit here
508 // and now allow anyone to switch again).
509 mService.mAppSwitchesAllowedTime = 0;
511 mService.mDidAppSwitch = true;
514 doPendingActivityLaunchesLocked(false);
517 mService.mWindowManager.deferSurfaceLayout();
518 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
519 true, options, inTask);
521 mService.mWindowManager.continueSurfaceLayout();
523 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
528 * Builds and returns an intent to launch the ephemeral installer.
530 private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
531 String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
532 final Intent nonEphemeralIntent = new Intent(origIntent);
533 nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
534 // Intent that is launched if the ephemeral package couldn't be installed
536 final IIntentSender failureIntentTarget = mService.getIntentSenderLocked(
537 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
538 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1,
539 new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType },
540 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
541 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
543 final Intent ephemeralIntent;
544 if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
545 // Force the intent to be directed to the ephemeral package
546 ephemeralIntent = new Intent(origIntent);
547 ephemeralIntent.setPackage(ephemeralPackage);
549 // Success intent goes back to the installer
550 ephemeralIntent = new Intent(launchIntent);
553 // Intent that is eventually launched if the ephemeral package was
554 // installed successfully. This will actually be launched by a platform
555 // broadcast receiver.
556 final IIntentSender successIntentTarget = mService.getIntentSenderLocked(
557 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
558 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0,
559 new Intent[]{ ephemeralIntent }, new String[]{ resolvedType },
560 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
561 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
563 // Finally build the actual intent to launch the ephemeral installer
564 int flags = launchIntent.getFlags();
565 final Intent intent = new Intent();
566 intent.setFlags(flags
567 | Intent.FLAG_ACTIVITY_NEW_TASK
568 | Intent.FLAG_ACTIVITY_CLEAR_TASK
569 | Intent.FLAG_ACTIVITY_NO_HISTORY
570 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
571 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
572 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
573 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
574 // TODO: Remove when the platform has fully implemented ephemeral apps
575 intent.setData(origIntent.getData().buildUpon().clearQuery().build());
579 void postStartActivityUncheckedProcessing(
580 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
581 ActivityStack targetStack) {
583 if (result < START_SUCCESS) {
584 // If someone asked to have the keyguard dismissed on the next activity start,
585 // but we are not actually doing an activity switch... just dismiss the keyguard now,
586 // because we probably want to see whatever is behind it.
587 mSupervisor.notifyActivityDrawnForKeyguard();
591 // We're waiting for an activity launch to finish, but that activity simply
592 // brought another activity to front. Let startActivityMayWait() know about
593 // this, so it waits for the new activity to become visible instead.
594 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
595 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
598 int startedActivityStackId = INVALID_STACK_ID;
599 if (r.task != null && r.task.stack != null) {
600 startedActivityStackId = r.task.stack.mStackId;
601 } else if (mTargetStack != null) {
602 startedActivityStackId = targetStack.mStackId;
605 // If we launched the activity from a no display activity that was launched from the home
606 // screen, we also need to start recents to un-minimize the docked stack, since the
607 // noDisplay activity will be finished shortly after.
608 // Note that some apps have trampoline activities without noDisplay being set. In that case,
609 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
610 // that tries to detect that case.
611 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
612 // visibility instead of using this flag.
613 final boolean noDisplayActivityOverHome = sourceRecord != null
614 && sourceRecord.noDisplay
615 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
616 if (startedActivityStackId == DOCKED_STACK_ID
617 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
618 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
619 final ActivityRecord topActivityHomeStack = homeStack != null
620 ? homeStack.topRunningActivityLocked() : null;
621 if (topActivityHomeStack == null
622 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
623 // We launch an activity while being in home stack, which means either launcher or
624 // recents into docked stack. We don't want the launched activity to be alone in a
625 // docked stack, so we want to immediately launch recents too.
626 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
627 mWindowManager.showRecentApps(true /* fromHome */);
632 if (startedActivityStackId == PINNED_STACK_ID
633 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
634 // The activity was already running in the pinned stack so it wasn't started, but either
635 // brought to the front or the new intent was delivered to it since it was already in
636 // front. Notify anyone interested in this piece of information.
637 mService.notifyPinnedActivityRestartAttemptLocked();
642 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
643 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
644 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
645 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
646 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
647 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
648 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
649 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
650 null /*container*/, null /*inTask*/);
651 if (mSupervisor.inResumeTopActivity) {
652 // If we are in resume section already, home activity will be initialized, but not
653 // resumed (to avoid recursive resume) and will stay that way until something pokes it
654 // again. We need to schedule another resume.
655 mSupervisor.scheduleResumeTopActivities();
659 void showConfirmDeviceCredential(int userId) {
660 // First, retrieve the stack that we want to resume after credential is confirmed.
661 ActivityStack targetStack;
662 ActivityStack fullscreenStack =
663 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
664 ActivityStack freeformStack =
665 mSupervisor.getStack(FREEFORM_WORKSPACE_STACK_ID);
666 if (fullscreenStack != null &&
667 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
668 // Single window case and the case that the docked stack is shown with fullscreen stack.
669 targetStack = fullscreenStack;
670 } else if (freeformStack != null &&
671 freeformStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
672 targetStack = freeformStack;
674 // The case that the docked stack is shown with recent.
675 targetStack = mSupervisor.getStack(HOME_STACK_ID);
677 if (targetStack == null) {
680 final KeyguardManager km = (KeyguardManager) mService.mContext
681 .getSystemService(Context.KEYGUARD_SERVICE);
682 final Intent credential =
683 km.createConfirmDeviceCredentialIntent(null, null, userId);
684 // For safety, check null here in case users changed the setting after the checking.
685 if (credential == null) {
688 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
689 if (activityRecord != null) {
690 final IIntentSender target = mService.getIntentSenderLocked(
691 ActivityManager.INTENT_SENDER_ACTIVITY,
692 activityRecord.launchedFromPackage,
693 activityRecord.launchedFromUid,
694 activityRecord.userId,
696 new Intent[] { activityRecord.intent },
697 new String[] { activityRecord.resolvedType },
698 PendingIntent.FLAG_CANCEL_CURRENT |
699 PendingIntent.FLAG_ONE_SHOT |
700 PendingIntent.FLAG_IMMUTABLE,
702 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
703 // Show confirm credentials activity.
704 startConfirmCredentialIntent(credential);
708 void startConfirmCredentialIntent(Intent intent) {
709 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
710 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
711 FLAG_ACTIVITY_TASK_ON_HOME);
712 final ActivityOptions options = ActivityOptions.makeBasic();
713 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
714 mService.mContext.startActivityAsUser(intent, options.toBundle(),
718 final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage,
719 Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
720 IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
721 int startFlags, ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult,
722 Configuration config, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
723 IActivityContainer iContainer, TaskRecord inTask) {
724 return startActivityMayWait(caller, callingUid, PID_NULL, UserHandle.USER_NULL,
725 callingPackage, intent, resolvedType, voiceSession, voiceInteractor, resultTo,
726 resultWho, requestCode, startFlags, profilerInfo, outResult, config, bOptions,
727 ignoreTargetSecurity, userId, iContainer, inTask);
730 final int startActivityMayWait(IApplicationThread caller, int callingUid,
731 int requestRealCallingPid, int requestRealCallingUid, String callingPackage,
732 Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
733 IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
734 int startFlags, ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult,
735 Configuration config, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
736 IActivityContainer iContainer, TaskRecord inTask) {
737 // Refuse possible leaked file descriptors
738 if (intent != null && intent.hasFileDescriptors()) {
739 throw new IllegalArgumentException("File descriptors passed in Intent");
741 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
742 boolean componentSpecified = intent.getComponent() != null;
744 // Save a copy in case ephemeral needs it
745 final Intent ephemeralIntent = new Intent(intent);
746 // Don't modify the client's object!
747 intent = new Intent(intent);
749 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
751 UserInfo userInfo = mSupervisor.getUserInfo(userId);
752 if (userInfo != null && userInfo.isManagedProfile()) {
753 // Special case for managed profiles, if attempting to launch non-cryto aware
754 // app in a locked managed profile from an unlocked parent allow it to resolve
755 // as user will be sent via confirm credentials to unlock the profile.
756 UserManager userManager = UserManager.get(mService.mContext);
757 boolean profileLockedAndParentUnlockingOrUnlocked = false;
758 long token = Binder.clearCallingIdentity();
760 UserInfo parent = userManager.getProfileParent(userId);
761 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
762 && userManager.isUserUnlockingOrUnlocked(parent.id)
763 && !userManager.isUserUnlockingOrUnlocked(userId);
765 Binder.restoreCallingIdentity(token);
767 if (profileLockedAndParentUnlockingOrUnlocked) {
768 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
769 PackageManager.MATCH_DIRECT_BOOT_AWARE
770 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
774 // Collect information about the target of the Intent.
775 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
777 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
778 ActivityStackSupervisor.ActivityContainer container =
779 (ActivityStackSupervisor.ActivityContainer)iContainer;
780 synchronized (mService) {
781 if (container != null && container.mParentActivity != null &&
782 container.mParentActivity.state != RESUMED) {
783 // Cannot start a child activity if the parent is not resumed.
784 return ActivityManager.START_CANCELED;
787 final int realCallingPid = requestRealCallingPid != PID_NULL
788 ? requestRealCallingPid
789 : Binder.getCallingPid();
790 final int realCallingUid = requestRealCallingUid != UserHandle.USER_NULL
791 ? requestRealCallingUid
792 : Binder.getCallingUid();
795 if (callingUid >= 0) {
797 } else if (caller == null) {
798 callingPid = realCallingPid;
799 callingUid = realCallingUid;
801 callingPid = callingUid = -1;
805 final ActivityStack stack;
806 if (container == null || container.mStack.isOnHomeDisplay()) {
807 stack = mSupervisor.mFocusedStack;
809 stack = container.mStack;
811 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
812 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
813 "Starting activity when config will change = " + stack.mConfigWillChange);
815 final long origId = Binder.clearCallingIdentity();
818 (aInfo.applicationInfo.privateFlags
819 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
820 // This may be a heavy-weight process! Check to see if we already
821 // have another, different heavy-weight process running.
822 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
823 final ProcessRecord heavy = mService.mHeavyWeightProcess;
824 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
825 || !heavy.processName.equals(aInfo.processName))) {
826 int appCallingUid = callingUid;
827 if (caller != null) {
828 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
829 if (callerApp != null) {
830 appCallingUid = callerApp.info.uid;
832 Slog.w(TAG, "Unable to find app for caller " + caller
833 + " (pid=" + callingPid + ") when starting: "
834 + intent.toString());
835 ActivityOptions.abort(options);
836 return ActivityManager.START_PERMISSION_DENIED;
840 IIntentSender target = mService.getIntentSenderLocked(
841 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
842 appCallingUid, userId, null, null, 0, new Intent[] { intent },
843 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
844 | PendingIntent.FLAG_ONE_SHOT, null);
846 Intent newIntent = new Intent();
847 if (requestCode >= 0) {
848 // Caller is requesting a result.
849 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
851 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
852 new IntentSender(target));
853 if (heavy.activities.size() > 0) {
854 ActivityRecord hist = heavy.activities.get(0);
855 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
857 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
860 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
862 newIntent.setFlags(intent.getFlags());
863 newIntent.setClassName("android",
864 HeavyWeightSwitcherActivity.class.getName());
868 callingUid = Binder.getCallingUid();
869 callingPid = Binder.getCallingPid();
870 componentSpecified = true;
871 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
872 aInfo = rInfo != null ? rInfo.activityInfo : null;
874 aInfo = mService.getActivityInfoForUser(aInfo, userId);
880 final ActivityRecord[] outRecord = new ActivityRecord[1];
881 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
882 aInfo, rInfo, voiceSession, voiceInteractor,
883 resultTo, resultWho, requestCode, callingPid,
884 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
885 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
888 Binder.restoreCallingIdentity(origId);
890 if (stack.mConfigWillChange) {
891 // If the caller also wants to switch to a new configuration,
892 // do so now. This allows a clean switch, as we are waiting
893 // for the current activity to pause (so we will not destroy
894 // it), and have not yet started the next activity.
895 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
896 "updateConfiguration()");
897 stack.mConfigWillChange = false;
898 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
899 "Updating to new configuration after starting activity.");
900 mService.updateConfigurationLocked(config, null, false);
903 if (outResult != null) {
904 outResult.result = res;
905 if (res == ActivityManager.START_SUCCESS) {
906 mSupervisor.mWaitingActivityLaunched.add(outResult);
910 } catch (InterruptedException e) {
912 } while (outResult.result != START_TASK_TO_FRONT
913 && !outResult.timeout && outResult.who == null);
914 if (outResult.result == START_TASK_TO_FRONT) {
915 res = START_TASK_TO_FRONT;
918 if (res == START_TASK_TO_FRONT) {
919 ActivityRecord r = stack.topRunningActivityLocked();
920 if (r.nowVisible && r.state == RESUMED) {
921 outResult.timeout = false;
922 outResult.who = new ComponentName(r.info.packageName, r.info.name);
923 outResult.totalTime = 0;
924 outResult.thisTime = 0;
926 outResult.thisTime = SystemClock.uptimeMillis();
927 mSupervisor.mWaitingActivityVisible.add(outResult);
931 } catch (InterruptedException e) {
933 } while (!outResult.timeout && outResult.who == null);
938 final ActivityRecord launchedActivity = mReusedActivity != null
939 ? mReusedActivity : outRecord[0];
940 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
945 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
946 Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions,
948 return startActivities(caller, callingUid, PID_NULL, UserHandle.USER_NULL, callingPackage,
949 intents, resolvedTypes, resultTo, bOptions, userId);
952 final int startActivities(IApplicationThread caller, int callingUid,
953 int incomingRealCallingPid, int incomingRealCallingUid, String callingPackage,
954 Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions,
956 if (intents == null) {
957 throw new NullPointerException("intents is null");
959 if (resolvedTypes == null) {
960 throw new NullPointerException("resolvedTypes is null");
962 if (intents.length != resolvedTypes.length) {
963 throw new IllegalArgumentException("intents are length different than resolvedTypes");
966 final int realCallingPid = incomingRealCallingPid != PID_NULL
967 ? incomingRealCallingPid
968 : Binder.getCallingPid();
970 final int realCallingUid = incomingRealCallingUid != UserHandle.USER_NULL
971 ? incomingRealCallingUid
972 : Binder.getCallingUid();
975 if (callingUid >= 0) {
977 } else if (caller == null) {
978 callingPid = realCallingPid;
979 callingUid = realCallingUid;
981 callingPid = callingUid = -1;
983 final long origId = Binder.clearCallingIdentity();
985 synchronized (mService) {
986 ActivityRecord[] outActivity = new ActivityRecord[1];
987 for (int i=0; i<intents.length; i++) {
988 Intent intent = intents[i];
989 if (intent == null) {
993 // Refuse possible leaked file descriptors
994 if (intent != null && intent.hasFileDescriptors()) {
995 throw new IllegalArgumentException("File descriptors passed in Intent");
998 boolean componentSpecified = intent.getComponent() != null;
1000 // Don't modify the client's object!
1001 intent = new Intent(intent);
1003 // Collect information about the target of the Intent.
1004 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
1006 // TODO: New, check if this is correct
1007 aInfo = mService.getActivityInfoForUser(aInfo, userId);
1009 if (aInfo != null &&
1010 (aInfo.applicationInfo.privateFlags
1011 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
1012 throw new IllegalArgumentException(
1013 "FLAG_CANT_SAVE_STATE not supported here");
1016 ActivityOptions options = ActivityOptions.fromBundle(
1017 i == intents.length - 1 ? bOptions : null);
1018 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
1019 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
1020 callingPid, callingUid, callingPackage,
1021 realCallingPid, realCallingUid, 0,
1022 options, false, componentSpecified, outActivity, null, null);
1027 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
1031 Binder.restoreCallingIdentity(origId);
1034 return START_SUCCESS;
1037 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
1038 // Trigger launch power hint if activity being launched is not in the current task
1039 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1040 final ActivityRecord curTop = (focusStack == null)
1041 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1042 if ((forceSend || (!mPowerHintSent && curTop != null &&
1043 curTop.task != null && mStartActivity != null &&
1044 curTop.task != mStartActivity.task )) &&
1045 mService.mLocalPowerManager != null) {
1046 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
1047 mPowerHintSent = true;
1051 void sendPowerHintForLaunchEndIfNeeded() {
1052 // Trigger launch power hint if activity is launched
1053 if (mPowerHintSent && mService.mLocalPowerManager != null) {
1054 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
1055 mPowerHintSent = false;
1059 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1060 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1061 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1063 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1066 computeLaunchingTaskFlags();
1068 computeSourceStack();
1070 mIntent.setFlags(mLaunchFlags);
1072 mReusedActivity = getReusableIntentActivity();
1074 final int preferredLaunchStackId =
1075 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1077 if (mReusedActivity != null) {
1078 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1079 // still needs to be a lock task mode violation since the task gets cleared out and
1080 // the device would otherwise leave the locked task.
1081 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
1082 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1083 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1084 mSupervisor.showLockTaskToast();
1085 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1086 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1089 if (mStartActivity.task == null) {
1090 mStartActivity.task = mReusedActivity.task;
1092 if (mReusedActivity.task.intent == null) {
1093 // This task was started because of movement of the activity based on affinity...
1094 // Now that we are actually launching it, we can assign the base intent.
1095 mReusedActivity.task.setIntent(mStartActivity);
1098 // This code path leads to delivering a new intent, we want to make sure we schedule it
1099 // as the first operation, in case the activity will be resumed as a result of later
1101 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1102 || mLaunchSingleInstance || mLaunchSingleTask) {
1103 // In this situation we want to remove all activities from the task up to the one
1104 // being started. In most cases this means we are resetting the task to its initial
1106 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
1107 mStartActivity, mLaunchFlags);
1109 if (top.frontOfTask) {
1110 // Activity aliases may mean we use different intents for the top activity,
1111 // so make sure the task now has the identity of the new intent.
1112 top.task.setIntent(mStartActivity);
1114 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1116 if (shouldActivityBeBroughtToFront(mReusedActivity)) {
1117 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1119 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1120 mStartActivity.launchedFromPackage);
1124 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1126 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
1128 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1129 // We don't need to start a new activity, and the client said not to do anything
1130 // if that is the case, so this is it! And for paranoia, make sure we have
1131 // correctly resumed the top activity.
1132 resumeTargetStackIfNeeded();
1133 return START_RETURN_INTENT_TO_CALLER;
1135 setTaskFromIntentActivity(mReusedActivity);
1137 if (!mAddingToTask && mReuseTask == null) {
1138 // We didn't do anything... but it was needed (a.k.a., client don't use that
1139 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1140 resumeTargetStackIfNeeded();
1141 return START_TASK_TO_FRONT;
1145 if (mStartActivity.packageName == null) {
1146 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1147 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1148 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1149 mStartActivity.requestCode, RESULT_CANCELED, null);
1151 ActivityOptions.abort(mOptions);
1152 return START_CLASS_NOT_FOUND;
1155 // If the activity being launched is the same as the one currently at the top, then
1156 // we need to check if it should only be launched once.
1157 final ActivityStack topStack = mSupervisor.mFocusedStack;
1158 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1159 final boolean dontStart = top != null && mStartActivity.resultTo == null
1160 && top.realActivity.equals(mStartActivity.realActivity)
1161 && top.userId == mStartActivity.userId
1162 && top.app != null && top.app.thread != null
1163 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1164 || mLaunchSingleTop || mLaunchSingleTask);
1166 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1167 // For paranoia, make sure we have correctly resumed the top activity.
1168 topStack.mLastPausedActivity = null;
1170 mSupervisor.resumeFocusedStackTopActivityLocked();
1172 ActivityOptions.abort(mOptions);
1173 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1174 // We don't need to start a new activity, and the client said not to do
1175 // anything if that is the case, so this is it!
1176 return START_RETURN_INTENT_TO_CALLER;
1178 top.deliverNewIntentLocked(
1179 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1181 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1182 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1183 mSupervisor.handleNonResizableTaskIfNeeded(
1184 top.task, preferredLaunchStackId, topStack.mStackId);
1186 return START_DELIVERED_TO_TOP;
1189 boolean newTask = false;
1190 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1191 ? mSourceRecord.task : null;
1193 // Should this be considered a new task?
1194 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1195 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1197 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1199 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1200 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1201 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1203 if (!mMovedOtherTask) {
1204 // If stack id is specified in activity options, usually it means that activity is
1205 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1206 // that case we check the target stack.
1207 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1208 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1210 } else if (mSourceRecord != null) {
1211 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1212 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1213 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1216 final int result = setTaskFromSourceRecord();
1217 if (result != START_SUCCESS) {
1220 } else if (mInTask != null) {
1221 // The caller is asking that the new activity be started in an explicit
1222 // task it has provided to us.
1223 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1224 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1225 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1228 final int result = setTaskFromInTask();
1229 if (result != START_SUCCESS) {
1233 // This not being started from an existing activity, and not part of a new task...
1234 // just put it in the top task, though these days this case should never happen.
1235 setTaskToCurrentTopOrCreateNewTask();
1238 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1239 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1241 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1242 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1245 EventLog.writeEvent(
1246 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1248 ActivityStack.logStartActivity(
1249 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1250 mTargetStack.mLastPausedActivity = null;
1252 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1254 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1256 if (!mLaunchTaskBehind) {
1257 // TODO(b/26381750): Remove this code after verification that all the decision
1258 // points above moved targetStack to the front which will also set the focus
1260 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1262 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1263 if (!mTargetStack.isFocusable()
1264 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1265 && mStartActivity != topTaskActivity)) {
1266 // If the activity is not focusable, we can't resume it, but still would like to
1267 // make sure it becomes visible as it starts (this will also trigger entry
1268 // animation). An example of this are PIP activities.
1269 // Also, we don't want to resume activities in a task that currently has an overlay
1270 // as the starting activity just needs to be in the visible paused state until the
1272 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1273 // Go ahead and tell window manager to execute app transition for this activity
1274 // since the app transition will not be triggered through the resume channel.
1275 mWindowManager.executeAppTransition();
1277 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1281 mTargetStack.addRecentActivityLocked(mStartActivity);
1283 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1285 mSupervisor.handleNonResizableTaskIfNeeded(
1286 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
1288 return START_SUCCESS;
1291 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1292 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1293 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1299 mCallingUid = r.launchedFromUid;
1300 mSourceRecord = sourceRecord;
1301 mVoiceSession = voiceSession;
1302 mVoiceInteractor = voiceInteractor;
1304 mLaunchBounds = getOverrideBounds(r, options, inTask);
1306 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1307 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1308 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1309 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1310 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1311 mLaunchTaskBehind = r.mLaunchTaskBehind
1312 && !mLaunchSingleTask && !mLaunchSingleInstance
1313 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1315 sendNewTaskResultRequestIfNeeded();
1317 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1318 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1321 // If we are actually going to launch in to a new task, there are some cases where
1322 // we further want to do multiple task.
1323 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1324 if (mLaunchTaskBehind
1325 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1326 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1330 // We'll invoke onUserLeaving before onPause only if the launching
1331 // activity did not explicitly state that this is an automated launch.
1332 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1333 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1334 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1336 // If the caller has asked not to resume at this point, we make note
1337 // of this in the record so that we can skip it when trying to find
1338 // the top running activity.
1339 mDoResume = doResume;
1340 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1341 r.delayedResume = true;
1345 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1346 r.mTaskOverlay = true;
1347 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1348 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1349 if (top != null && !top.visible) {
1351 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1354 mAvoidMoveToFront = true;
1358 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1361 // In some flows in to this function, we retrieve the task record and hold on to it
1362 // without a lock before calling back in to here... so the task at this point may
1363 // not actually be in recents. Check for that, and if it isn't in recents just
1364 // consider it invalid.
1365 if (inTask != null && !inTask.inRecents) {
1366 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1370 mStartFlags = startFlags;
1371 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1372 // is the same as the one making the call... or, as a special case, if we do not know
1373 // the caller then we count the current top activity as the caller.
1374 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1375 ActivityRecord checkedCaller = sourceRecord;
1376 if (checkedCaller == null) {
1377 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1380 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1381 // Caller is not the same as launcher, so always needed.
1382 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1386 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1389 private void sendNewTaskResultRequestIfNeeded() {
1390 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1391 && mStartActivity.resultTo.task.stack != null) {
1392 // For whatever reason this activity is being launched into a new task...
1393 // yet the caller has requested a result back. Well, that is pretty messed up,
1394 // so instead immediately send back a cancel and let the new task continue launched
1395 // as normal without a dependency on its originator.
1396 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1397 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1398 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1399 mStartActivity.resultTo = null;
1403 private void computeLaunchingTaskFlags() {
1404 // If the caller is not coming from another activity, but has given us an explicit task into
1405 // which they would like us to launch the new activity, then let's see about doing that.
1406 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1407 final Intent baseIntent = mInTask.getBaseIntent();
1408 final ActivityRecord root = mInTask.getRootActivity();
1409 if (baseIntent == null) {
1410 ActivityOptions.abort(mOptions);
1411 throw new IllegalArgumentException("Launching into task without base intent: "
1415 // If this task is empty, then we are adding the first activity -- it
1416 // determines the root, and must be launching as a NEW_TASK.
1417 if (mLaunchSingleInstance || mLaunchSingleTask) {
1418 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1419 ActivityOptions.abort(mOptions);
1420 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1421 + mStartActivity + " into different task " + mInTask);
1424 ActivityOptions.abort(mOptions);
1425 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1426 + " has root " + root + " but target is singleInstance/Task");
1430 // If task is empty, then adopt the interesting intent launch flags in to the
1431 // activity being started.
1433 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1434 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1435 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1436 | (baseIntent.getFlags() & flagsOfInterest);
1437 mIntent.setFlags(mLaunchFlags);
1438 mInTask.setIntent(mStartActivity);
1439 mAddingToTask = true;
1441 // If the task is not empty and the caller is asking to start it as the root of
1442 // a new task, then we don't actually want to start this on the task. We will
1443 // bring the task to the front, and possibly give it a new intent.
1444 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1445 mAddingToTask = false;
1448 mAddingToTask = true;
1451 mReuseTask = mInTask;
1454 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1455 // when in freeform workspace.
1456 // Also put noDisplay activities in the source task. These by itself can be placed
1457 // in any task/stack, however it could launch other activities like ResolverActivity,
1458 // and we want those to stay in the original task.
1459 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1460 && mSourceRecord.isFreeform()) {
1461 mAddingToTask = true;
1465 if (mInTask == null) {
1466 if (mSourceRecord == null) {
1467 // This activity is not being started from another... in this
1468 // case we -always- start a new task.
1469 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1470 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1471 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1472 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1474 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1475 // The original activity who is starting us is running as a single
1476 // instance... this new activity it is starting must go on its
1478 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1479 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1480 // The activity being started is a single instance... it always
1481 // gets launched into its own task.
1482 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1487 private void computeSourceStack() {
1488 if (mSourceRecord == null) {
1489 mSourceStack = null;
1492 if (!mSourceRecord.finishing) {
1493 mSourceStack = mSourceRecord.task.stack;
1497 // If the source is finishing, we can't further count it as our source. This is because the
1498 // task it is associated with may now be empty and on its way out, so we don't want to
1499 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1500 // a task for it. But save the task information so it can be used when creating the new task.
1501 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1502 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1503 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1504 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1505 mNewTaskInfo = mSourceRecord.info;
1506 mNewTaskIntent = mSourceRecord.task.intent;
1508 mSourceRecord = null;
1509 mSourceStack = null;
1513 * Decide whether the new activity should be inserted into an existing task. Returns null
1514 * if not or an ActivityRecord with the task into which the new activity should be added.
1516 private ActivityRecord getReusableIntentActivity() {
1517 // We may want to try to place the new activity in to an existing task. We always
1518 // do this if the target activity is singleTask or singleInstance; we will also do
1519 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1520 // us to still place it in a new task: multi task, always doc mode, or being asked to
1521 // launch this as a new task behind the current one.
1522 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1523 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1524 || mLaunchSingleInstance || mLaunchSingleTask;
1525 // If bring to front is requested, and no result is requested and we have not been given
1526 // an explicit task to launch in to, and we can find a task that was started with this
1527 // same component, then instead of launching bring that one to the front.
1528 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1529 ActivityRecord intentActivity = null;
1530 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1531 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1532 intentActivity = task != null ? task.getTopActivity() : null;
1533 } else if (putIntoExistingTask) {
1534 if (mLaunchSingleInstance) {
1535 // There can be one and only one instance of single instance activity in the
1536 // history, and it is always in its own unique task, so we do a special search.
1537 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
1538 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1539 // For the launch adjacent case we only want to put the activity in an existing
1540 // task if the activity already exists in the history.
1541 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1542 !mLaunchSingleTask);
1544 // Otherwise find the best task to put the activity in.
1545 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1548 return intentActivity;
1551 private boolean shouldActivityBeBroughtToFront(ActivityRecord intentActivity) {
1552 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1553 ActivityRecord curTop = (focusStack == null)
1554 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1556 return curTop != null
1557 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1558 && !mAvoidMoveToFront;
1561 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1562 mTargetStack = intentActivity.task.stack;
1563 mTargetStack.mLastPausedActivity = null;
1564 // If the target task is not in the front, then we need to bring it to the front...
1565 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1566 // the same behavior as if a new instance was being started, which means not bringing it
1567 // to the front if the caller is not itself in the front.
1568 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1570 if (shouldActivityBeBroughtToFront(intentActivity)) {
1571 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1572 mSourceStack.topActivity().task == mSourceRecord.task)) {
1573 // We really do want to push this one into the user's face, right now.
1574 if (mLaunchTaskBehind && mSourceRecord != null) {
1575 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1577 mMovedOtherTask = true;
1579 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1580 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1581 // So no point resuming any of the activities here, it just wastes one extra
1582 // resuming, plus enter AND exit transitions.
1583 // Here we only want to bring the target stack forward. Transition will be applied
1584 // to the new activity that's started after the old ones are gone.
1585 final boolean willClearTask =
1586 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1587 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1588 if (!willClearTask) {
1589 final ActivityStack launchStack = getLaunchStack(
1590 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
1591 if (launchStack == null || launchStack == mTargetStack) {
1592 // We only want to move to the front, if we aren't going to launch on a
1593 // different stack. If we launch on a different stack, we will put the
1594 // task on top there.
1595 mTargetStack.moveTaskToFrontLocked(
1596 intentActivity.task, mNoAnimation, mOptions,
1597 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1598 mMovedToFront = true;
1599 } else if (launchStack.mStackId == DOCKED_STACK_ID
1600 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1601 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1602 // If we want to launch adjacent and mTargetStack is not the computed
1603 // launch stack - move task to top of computed stack.
1604 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1605 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1608 // TODO: This should be reevaluated in MW v2.
1609 // We choose to move task to front instead of launching it adjacent
1610 // when specific stack was requested explicitly and it appeared to be
1611 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1612 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1613 mOptions, mStartActivity.appTimeTracker,
1614 "bringToFrontInsteadOfAdjacentLaunch");
1616 mMovedToFront = true;
1620 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
1623 if (!mMovedToFront && mDoResume) {
1624 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1625 + " from " + intentActivity);
1626 mTargetStack.moveToFront("intentActivityFound");
1629 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1630 mTargetStack.mStackId);
1632 // If the caller has requested that the target task be reset, then do so.
1633 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1634 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1636 return intentActivity;
1639 private void updateTaskReturnToType(
1640 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1641 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1642 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1643 // Caller wants to appear on home activity.
1644 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1646 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1647 // Task will be launched over the home stack, so return home.
1648 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1652 // Else we are coming from an application stack so return to an application.
1653 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1656 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1657 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1658 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1659 // The caller has requested to completely replace any existing task with its new
1660 // activity. Well that should not be too hard...
1661 intentActivity.task.performClearTaskLocked();
1662 intentActivity.task.setIntent(mStartActivity);
1663 mReuseTask = intentActivity.task;
1664 // When we clear the task - focus will be adjusted, which will bring another task
1665 // to top before we launch the activity we need. This will temporary swap their
1666 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1667 mMovedOtherTask = true;
1668 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1669 || mLaunchSingleInstance || mLaunchSingleTask) {
1670 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1673 // A special case: we need to start the activity because it is not currently
1674 // running, and the caller has asked to clear the current task to have this
1675 // activity at the top.
1676 mAddingToTask = true;
1677 // Now pretend like this activity is being started by the top of its task, so it
1678 // is put in the right place.
1679 mSourceRecord = intentActivity;
1680 final TaskRecord task = mSourceRecord.task;
1681 if (task != null && task.stack == null) {
1682 // Target stack got cleared when we all activities were removed above.
1683 // Go ahead and reset it.
1684 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1685 null /* bounds */, mLaunchFlags, mOptions);
1686 mTargetStack.addTask(task,
1687 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1690 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1691 // In this case the top activity on the task is the same as the one being launched,
1692 // so we take that as a request to bring the task to the foreground. If the top
1693 // activity in the task is the root activity, deliver this new intent to it if it
1695 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1696 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1697 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1698 intentActivity.task);
1699 if (intentActivity.frontOfTask) {
1700 intentActivity.task.setIntent(mStartActivity);
1702 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1703 mStartActivity.launchedFromPackage);
1704 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
1705 // In this case we are launching the root activity of the task, but with a
1706 // different intent. We should start a new instance on top.
1707 mAddingToTask = true;
1708 mSourceRecord = intentActivity;
1710 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1711 // In this case an activity is being launched in to an existing task, without
1712 // resetting that task. This is typically the situation of launching an activity
1713 // from a notification or shortcut. We want to place the new activity on top of the
1715 mAddingToTask = true;
1716 mSourceRecord = intentActivity;
1717 } else if (!intentActivity.task.rootWasReset) {
1718 // In this case we are launching into an existing task that has not yet been started
1719 // from its front door. The current task has been brought to the front. Ideally,
1720 // we'd probably like to place this new task at the bottom of its stack, but that's
1721 // a little hard to do with the current organization of the code so for now we'll
1723 intentActivity.task.setIntent(mStartActivity);
1727 private void resumeTargetStackIfNeeded() {
1729 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1730 if (!mMovedToFront) {
1731 // Make sure to notify Keyguard as well if we are not running an app transition
1733 mSupervisor.notifyActivityDrawnForKeyguard();
1736 ActivityOptions.abort(mOptions);
1738 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1741 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1742 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1745 if (mReuseTask == null) {
1746 final TaskRecord task = mTargetStack.createTaskRecord(
1747 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1748 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1749 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1750 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1751 mStartActivity.setTask(task, taskToAffiliate);
1752 if (mLaunchBounds != null) {
1753 final int stackId = mTargetStack.mStackId;
1754 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1755 mService.resizeStack(
1756 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1758 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1761 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1762 "Starting new activity " +
1763 mStartActivity + " in new task " + mStartActivity.task);
1765 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1769 private int setTaskFromSourceRecord() {
1770 final TaskRecord sourceTask = mSourceRecord.task;
1771 // We only want to allow changing stack if the target task is not the top one,
1772 // otherwise we would move the launching task to the other side, rather than show
1773 // two side by side.
1774 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1775 if (moveStackAllowed) {
1776 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1780 if (mTargetStack == null) {
1781 mTargetStack = sourceTask.stack;
1782 } else if (mTargetStack != sourceTask.stack) {
1783 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1784 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1787 mTargetStack.moveToFront("sourceStackToFront");
1789 final TaskRecord topTask = mTargetStack.topTask();
1790 if (topTask != sourceTask && !mAvoidMoveToFront) {
1791 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1792 mStartActivity.appTimeTracker, "sourceTaskToFront");
1794 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1795 // In this case, we are adding the activity to an existing task, but the caller has
1796 // asked to clear that task if the activity is already running.
1797 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1798 mKeepCurTransition = true;
1800 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1801 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1802 // For paranoia, make sure we have correctly resumed the top activity.
1803 mTargetStack.mLastPausedActivity = null;
1805 mSupervisor.resumeFocusedStackTopActivityLocked();
1807 ActivityOptions.abort(mOptions);
1808 return START_DELIVERED_TO_TOP;
1810 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1811 // In this case, we are launching an activity in our own task that may already be
1812 // running somewhere in the history, and we want to shuffle it to the front of the
1814 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1816 final TaskRecord task = top.task;
1817 task.moveActivityToFrontLocked(top);
1818 top.updateOptionsLocked(mOptions);
1819 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1820 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1821 mTargetStack.mLastPausedActivity = null;
1823 mSupervisor.resumeFocusedStackTopActivityLocked();
1825 return START_DELIVERED_TO_TOP;
1829 // An existing activity is starting this new activity, so we want to keep the new one in
1830 // the same task as the one that is starting it.
1831 mStartActivity.setTask(sourceTask, null);
1832 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1833 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1834 return START_SUCCESS;
1837 private int setTaskFromInTask() {
1838 if (mLaunchBounds != null) {
1839 mInTask.updateOverrideConfiguration(mLaunchBounds);
1840 int stackId = mInTask.getLaunchStackId();
1841 if (stackId != mInTask.stack.mStackId) {
1842 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
1843 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1844 stackId = stack.mStackId;
1846 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1847 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1850 mTargetStack = mInTask.stack;
1851 mTargetStack.moveTaskToFrontLocked(
1852 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1854 // Check whether we should actually launch the new activity in to the task,
1855 // or just reuse the current activity on top.
1856 ActivityRecord top = mInTask.getTopActivity();
1857 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1858 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1859 || mLaunchSingleTop || mLaunchSingleTask) {
1860 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1861 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1862 // We don't need to start a new activity, and the client said not to do
1863 // anything if that is the case, so this is it!
1864 return START_RETURN_INTENT_TO_CALLER;
1866 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1867 return START_DELIVERED_TO_TOP;
1871 if (!mAddingToTask) {
1872 // We don't actually want to have this activity added to the task, so just
1873 // stop here but still tell the caller that we consumed the intent.
1874 ActivityOptions.abort(mOptions);
1875 return START_TASK_TO_FRONT;
1878 mStartActivity.setTask(mInTask, null);
1879 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1880 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1882 return START_SUCCESS;
1885 private void setTaskToCurrentTopOrCreateNewTask() {
1886 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1889 mTargetStack.moveToFront("addingToTopTask");
1891 final ActivityRecord prev = mTargetStack.topActivity();
1892 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1893 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1894 mStartActivity.info, mIntent, null, null, true);
1895 mStartActivity.setTask(task, null);
1896 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1897 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1898 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1901 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1902 boolean launchSingleTask, int launchFlags) {
1903 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1904 (launchSingleInstance || launchSingleTask)) {
1905 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1906 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1907 "\"singleInstance\" or \"singleTask\"");
1909 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1911 switch (r.info.documentLaunchMode) {
1912 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1914 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1915 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1917 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1918 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1920 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1921 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1928 final void doPendingActivityLaunchesLocked(boolean doResume) {
1929 while (!mPendingActivityLaunches.isEmpty()) {
1930 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1931 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
1933 final int result = startActivityUnchecked(
1934 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1935 postStartActivityUncheckedProcessing(
1936 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1938 } catch (Exception e) {
1939 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1940 pal.sendErrorResult(e.getMessage());
1945 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1946 int launchFlags, ActivityOptions aOptions) {
1947 final TaskRecord task = r.task;
1948 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1949 return mSupervisor.mHomeStack;
1952 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
1953 if (stack != null) {
1957 if (task != null && task.stack != null) {
1959 if (stack.isOnHomeDisplay()) {
1960 if (mSupervisor.mFocusedStack != stack) {
1961 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1962 "computeStackFocus: Setting " + "focused stack to r=" + r
1965 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1966 "computeStackFocus: Focused stack already="
1967 + mSupervisor.mFocusedStack);
1973 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1974 if (container != null) {
1975 // The first time put it on the desired stack, after this put on task stack.
1976 r.mInitialActivityContainer = null;
1977 return container.mStack;
1980 // The fullscreen stack can contain any task regardless of if the task is resizeable
1981 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1982 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1983 // we can also put it in the focused stack.
1984 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1985 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1986 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1987 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
1988 if (canUseFocusedStack && (!newTask
1989 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1990 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1991 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1992 return mSupervisor.mFocusedStack;
1995 // We first try to put the task in the first dynamic stack.
1996 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1997 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1998 stack = homeDisplayStacks.get(stackNdx);
1999 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
2000 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2001 "computeStackFocus: Setting focused stack=" + stack);
2006 // If there is no suitable dynamic stack then we figure out which static stack to use.
2007 final int stackId = task != null ? task.getLaunchStackId() :
2008 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2009 FULLSCREEN_WORKSPACE_STACK_ID;
2010 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
2011 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2012 + r + " stackId=" + stack.mStackId);
2016 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
2017 ActivityOptions aOptions) {
2019 // We are reusing a task, keep the stack!
2020 if (mReuseTask != null) {
2021 return mReuseTask.stack;
2024 final int launchStackId =
2025 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2027 if (isValidLaunchStackId(launchStackId, r)) {
2028 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
2029 } else if (launchStackId == DOCKED_STACK_ID) {
2030 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2031 // for this activity, so we put the activity in the fullscreen stack.
2032 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2035 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
2038 // Otherwise handle adjacent launch.
2040 // The parent activity doesn't want to launch the activity on top of itself, but
2041 // instead tries to put it onto other side in side-by-side mode.
2042 final ActivityStack parentStack = task != null ? task.stack
2043 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2044 : mSupervisor.mFocusedStack;
2046 if (parentStack != mSupervisor.mFocusedStack) {
2047 // If task's parent stack is not focused - use it during adjacent launch.
2050 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2051 // If task is already on top of focused stack - use it. We don't want to move the
2052 // existing focused task to adjacent stack, just deliver new intent in this case.
2053 return mSupervisor.mFocusedStack;
2056 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2057 // If parent was in docked stack, the natural place to launch another activity
2058 // will be fullscreen, so it can appear alongside the docked window.
2059 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2062 // If the parent is not in the docked stack, we check if there is docked window
2063 // and if yes, we will launch into that stack. If not, we just put the new
2064 // activity into parent's stack, because we can't find a better place.
2065 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2066 if (dockedStack != null
2067 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2068 // There is a docked stack, but it isn't visible, so we can't launch into that.
2077 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2078 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2079 || !StackId.isStaticStack(stackId)) {
2083 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2084 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2088 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2092 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2096 final boolean supportsPip = mService.mSupportsPictureInPicture
2097 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2098 if (stackId == PINNED_STACK_ID && !supportsPip) {
2104 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2105 Rect newBounds = null;
2106 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2107 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2108 options, options.getLaunchStackId())) {
2109 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2115 void setWindowManager(WindowManagerService wm) {
2116 mWindowManager = wm;
2119 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2120 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2121 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2122 if (pal.stack == stack) {
2123 mPendingActivityLaunches.remove(palNdx);