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.RemoteException;
106 import android.os.SystemClock;
107 import android.os.UserHandle;
108 import android.os.UserManager;
109 import android.service.voice.IVoiceInteractionSession;
110 import android.util.EventLog;
111 import android.util.Slog;
112 import android.view.Display;
114 import com.android.internal.app.HeavyWeightSwitcherActivity;
115 import com.android.internal.app.IVoiceInteractor;
116 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
117 import com.android.server.wm.WindowManagerService;
119 import java.util.ArrayList;
122 * Controller for interpreting how and then launching activities.
124 * This class collects all the logic for determining how an intent and flags should be turned into
125 * an activity and associated task and stack.
127 class ActivityStarter {
128 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
129 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
130 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
131 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
132 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
134 private final ActivityManagerService mService;
135 private final ActivityStackSupervisor mSupervisor;
136 private ActivityStartInterceptor mInterceptor;
137 private WindowManagerService mWindowManager;
139 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
141 // Share state variable among methods when starting an activity.
142 private ActivityRecord mStartActivity;
143 private ActivityRecord mReusedActivity;
144 private Intent mIntent;
145 private int mCallingUid;
146 private ActivityOptions mOptions;
148 private boolean mLaunchSingleTop;
149 private boolean mLaunchSingleInstance;
150 private boolean mLaunchSingleTask;
151 private boolean mLaunchTaskBehind;
152 private int mLaunchFlags;
154 private Rect mLaunchBounds;
156 private ActivityRecord mNotTop;
157 private boolean mDoResume;
158 private int mStartFlags;
159 private ActivityRecord mSourceRecord;
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 // Indicates that we moved other task and are going to put something on top soon, so
170 // we don't want to show it redundantly or accidentally change what's shown below.
171 private boolean mMovedOtherTask;
172 private boolean mMovedToFront;
173 private boolean mNoAnimation;
174 private boolean mKeepCurTransition;
175 private boolean mAvoidMoveToFront;
177 private IVoiceInteractionSession mVoiceSession;
178 private IVoiceInteractor mVoiceInteractor;
180 private void reset() {
181 mStartActivity = null;
186 mLaunchSingleTop = false;
187 mLaunchSingleInstance = false;
188 mLaunchSingleTask = false;
189 mLaunchTaskBehind = false;
192 mLaunchBounds = null;
197 mSourceRecord = null;
200 mAddingToTask = false;
204 mNewTaskIntent = null;
208 mMovedOtherTask = false;
209 mMovedToFront = false;
210 mNoAnimation = false;
211 mKeepCurTransition = false;
212 mAvoidMoveToFront = false;
214 mVoiceSession = null;
215 mVoiceInteractor = null;
218 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
220 mSupervisor = supervisor;
221 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
224 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
225 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
226 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
227 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
228 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
229 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
230 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
232 int err = ActivityManager.START_SUCCESS;
234 ProcessRecord callerApp = null;
235 if (caller != null) {
236 callerApp = mService.getRecordForAppLocked(caller);
237 if (callerApp != null) {
238 callingPid = callerApp.pid;
239 callingUid = callerApp.info.uid;
241 Slog.w(TAG, "Unable to find app for caller " + caller
242 + " (pid=" + callingPid + ") when starting: "
243 + intent.toString());
244 err = ActivityManager.START_PERMISSION_DENIED;
248 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
250 if (err == ActivityManager.START_SUCCESS) {
251 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
252 + "} from uid " + callingUid
253 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
254 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
255 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
256 container.mActivityDisplay.mDisplayId)));
259 ActivityRecord sourceRecord = null;
260 ActivityRecord resultRecord = null;
261 if (resultTo != null) {
262 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
263 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
264 "Will send result to " + resultTo + " " + sourceRecord);
265 if (sourceRecord != null) {
266 if (requestCode >= 0 && !sourceRecord.finishing) {
267 resultRecord = sourceRecord;
272 final int launchFlags = intent.getFlags();
274 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
275 // Transfer the result target from the source activity to the new
276 // one being started, including any failures.
277 if (requestCode >= 0) {
278 ActivityOptions.abort(options);
279 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
281 resultRecord = sourceRecord.resultTo;
282 if (resultRecord != null && !resultRecord.isInStackLocked()) {
285 resultWho = sourceRecord.resultWho;
286 requestCode = sourceRecord.requestCode;
287 sourceRecord.resultTo = null;
288 if (resultRecord != null) {
289 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
291 if (sourceRecord.launchedFromUid == callingUid) {
292 // The new activity is being launched from the same uid as the previous
293 // activity in the flow, and asking to forward its result back to the
294 // previous. In this case the activity is serving as a trampoline between
295 // the two, so we also want to update its launchedFromPackage to be the
296 // same as the previous activity. Note that this is safe, since we know
297 // these two packages come from the same uid; the caller could just as
298 // well have supplied that same package name itself. This specifially
299 // deals with the case of an intent picker/chooser being launched in the app
300 // flow to redirect to an activity picked by the user, where we want the final
301 // activity to consider it to have been launched by the previous app activity.
302 callingPackage = sourceRecord.launchedFromPackage;
306 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
307 // We couldn't find a class that can handle the given Intent.
308 // That's the end of that!
309 err = ActivityManager.START_INTENT_NOT_RESOLVED;
312 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
313 // We couldn't find the specific class specified in the Intent.
314 // Also the end of the line.
315 err = ActivityManager.START_CLASS_NOT_FOUND;
318 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
319 && sourceRecord.task.voiceSession != null) {
320 // If this activity is being launched as part of a voice session, we need
321 // to ensure that it is safe to do so. If the upcoming activity will also
322 // be part of the voice session, we can only launch it if it has explicitly
323 // said it supports the VOICE category, or it is a part of the calling app.
324 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
325 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
327 intent.addCategory(Intent.CATEGORY_VOICE);
328 if (!AppGlobals.getPackageManager().activitySupportsIntent(
329 intent.getComponent(), intent, resolvedType)) {
331 "Activity being started in current voice task does not support voice: "
333 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
335 } catch (RemoteException e) {
336 Slog.w(TAG, "Failure checking voice capabilities", e);
337 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
342 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
343 // If the caller is starting a new voice session, just make sure the target
344 // is actually allowing it to run this way.
346 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
347 intent, resolvedType)) {
349 "Activity being started in new voice task does not support: "
351 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
353 } catch (RemoteException e) {
354 Slog.w(TAG, "Failure checking voice capabilities", e);
355 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
359 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
361 if (err != START_SUCCESS) {
362 if (resultRecord != null) {
363 resultStack.sendActivityResultLocked(
364 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
366 ActivityOptions.abort(options);
370 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
371 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
372 resultRecord, resultStack, options);
373 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
374 callingPid, resolvedType, aInfo.applicationInfo);
376 if (mService.mController != null) {
378 // The Intent we give to the watcher has the extra data
379 // stripped off, since it can contain private information.
380 Intent watchIntent = intent.cloneFilter();
381 abort |= !mService.mController.activityStarting(watchIntent,
382 aInfo.applicationInfo.packageName);
383 } catch (RemoteException e) {
384 mService.mController = null;
388 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
389 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
391 intent = mInterceptor.mIntent;
392 rInfo = mInterceptor.mRInfo;
393 aInfo = mInterceptor.mAInfo;
394 resolvedType = mInterceptor.mResolvedType;
395 inTask = mInterceptor.mInTask;
396 callingPid = mInterceptor.mCallingPid;
397 callingUid = mInterceptor.mCallingUid;
398 options = mInterceptor.mActivityOptions;
400 if (resultRecord != null) {
401 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
402 RESULT_CANCELED, null);
404 // We pretend to the caller that it was really started, but
405 // they will just get a cancel result.
406 ActivityOptions.abort(options);
407 return START_SUCCESS;
410 // If permissions need a review before any of the app components can run, we
411 // launch the review activity and pass a pending intent to start the activity
412 // we are to launching now after the review is completed.
413 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
414 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
415 aInfo.packageName, userId)) {
416 IIntentSender target = mService.getIntentSenderLocked(
417 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
418 callingUid, userId, null, null, 0, new Intent[]{intent},
419 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
420 | PendingIntent.FLAG_ONE_SHOT, null);
422 final int flags = intent.getFlags();
423 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
424 newIntent.setFlags(flags
425 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
426 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
427 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
428 if (resultRecord != null) {
429 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
434 callingUid = realCallingUid;
435 callingPid = realCallingPid;
437 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
438 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
439 null /*profilerInfo*/);
441 if (DEBUG_PERMISSIONS_REVIEW) {
442 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
443 true, false) + "} from uid " + callingUid + " on display "
444 + (container == null ? (mSupervisor.mFocusedStack == null ?
445 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
446 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
447 container.mActivityDisplay.mDisplayId)));
452 // If we have an ephemeral app, abort the process of launching the resolved intent.
453 // Instead, launch the ephemeral installer. Once the installer is finished, it
454 // starts either the intent we resolved here [on install error] or the ephemeral
455 // app [on install success].
456 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
457 // Create a pending intent to start the intent resolved here.
458 final IIntentSender failureTarget = mService.getIntentSenderLocked(
459 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
460 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
461 new String[]{ resolvedType },
462 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
463 | PendingIntent.FLAG_IMMUTABLE, null);
465 // Create a pending intent to start the ephemeral application; force it to be
466 // directed to the ephemeral package.
467 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
468 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
469 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
470 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
471 new String[]{ resolvedType },
472 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
473 | PendingIntent.FLAG_IMMUTABLE, null);
475 int flags = intent.getFlags();
476 intent = new Intent();
477 intent.setFlags(flags
478 | Intent.FLAG_ACTIVITY_NEW_TASK
479 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
480 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
481 rInfo.ephemeralResolveInfo.getPackageName());
482 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
483 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
486 callingUid = realCallingUid;
487 callingPid = realCallingPid;
489 rInfo = rInfo.ephemeralInstaller;
490 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
493 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
494 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
495 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
496 options, sourceRecord);
497 if (outActivity != null) {
501 if (r.appTimeTracker == null && sourceRecord != null) {
502 // If the caller didn't specify an explicit time tracker, we want to continue
503 // tracking under any it has.
504 r.appTimeTracker = sourceRecord.appTimeTracker;
507 final ActivityStack stack = mSupervisor.mFocusedStack;
508 if (voiceSession == null && (stack.mResumedActivity == null
509 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
510 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
511 realCallingPid, realCallingUid, "Activity start")) {
512 PendingActivityLaunch pal = new PendingActivityLaunch(r,
513 sourceRecord, startFlags, stack, callerApp);
514 mPendingActivityLaunches.add(pal);
515 ActivityOptions.abort(options);
516 return ActivityManager.START_SWITCHES_CANCELED;
520 if (mService.mDidAppSwitch) {
521 // This is the second allowed switch since we stopped switches,
522 // so now just generally allow switches. Use case: user presses
523 // home (switches disabled, switch to home, mDidAppSwitch now true);
524 // user taps a home icon (coming from home so allowed, we hit here
525 // and now allow anyone to switch again).
526 mService.mAppSwitchesAllowedTime = 0;
528 mService.mDidAppSwitch = true;
531 doPendingActivityLaunchesLocked(false);
534 mService.mWindowManager.deferSurfaceLayout();
535 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
536 true, options, inTask);
538 mService.mWindowManager.continueSurfaceLayout();
540 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
544 void postStartActivityUncheckedProcessing(
545 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
546 ActivityStack targetStack) {
548 if (result < START_SUCCESS) {
549 // If someone asked to have the keyguard dismissed on the next activity start,
550 // but we are not actually doing an activity switch... just dismiss the keyguard now,
551 // because we probably want to see whatever is behind it.
552 mSupervisor.notifyActivityDrawnForKeyguard();
556 // We're waiting for an activity launch to finish, but that activity simply
557 // brought another activity to front. Let startActivityMayWait() know about
558 // this, so it waits for the new activity to become visible instead.
559 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
560 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
563 int startedActivityStackId = INVALID_STACK_ID;
564 if (r.task != null && r.task.stack != null) {
565 startedActivityStackId = r.task.stack.mStackId;
566 } else if (mTargetStack != null) {
567 startedActivityStackId = targetStack.mStackId;
570 // If we launched the activity from a no display activity that was launched from the home
571 // screen, we also need to start recents to un-minimize the docked stack, since the
572 // noDisplay activity will be finished shortly after.
573 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
574 // visibility instead of using this flag.
575 final boolean noDisplayActivityOverHome = sourceRecord != null
576 && sourceRecord.noDisplay
577 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
578 if (startedActivityStackId == DOCKED_STACK_ID
579 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
580 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
581 final ActivityRecord topActivityHomeStack = homeStack != null
582 ? homeStack.topRunningActivityLocked() : null;
583 if (topActivityHomeStack == null
584 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
585 // We launch an activity while being in home stack, which means either launcher or
586 // recents into docked stack. We don't want the launched activity to be alone in a
587 // docked stack, so we want to immediately launch recents too.
588 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
589 mWindowManager.showRecentApps(true /* fromHome */);
594 if (startedActivityStackId == PINNED_STACK_ID
595 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
596 // The activity was already running in the pinned stack so it wasn't started, but either
597 // brought to the front or the new intent was delivered to it since it was already in
598 // front. Notify anyone interested in this piece of information.
599 mService.notifyPinnedActivityRestartAttemptLocked();
604 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
605 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
606 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
607 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
608 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
609 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
610 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
611 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
612 null /*container*/, null /*inTask*/);
613 if (mSupervisor.inResumeTopActivity) {
614 // If we are in resume section already, home activity will be initialized, but not
615 // resumed (to avoid recursive resume) and will stay that way until something pokes it
616 // again. We need to schedule another resume.
617 mSupervisor.scheduleResumeTopActivities();
621 void showConfirmDeviceCredential(int userId) {
622 // First, retrieve the stack that we want to resume after credential is confirmed.
623 ActivityStack targetStack;
624 ActivityStack fullscreenStack =
625 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
626 ActivityStack freeformStack =
627 mSupervisor.getStack(FREEFORM_WORKSPACE_STACK_ID);
628 if (fullscreenStack != null &&
629 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
630 // Single window case and the case that the docked stack is shown with fullscreen stack.
631 targetStack = fullscreenStack;
632 } else if (freeformStack != null &&
633 freeformStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
634 targetStack = freeformStack;
636 // The case that the docked stack is shown with recent.
637 targetStack = mSupervisor.getStack(HOME_STACK_ID);
639 if (targetStack == null) {
642 final KeyguardManager km = (KeyguardManager) mService.mContext
643 .getSystemService(Context.KEYGUARD_SERVICE);
644 final Intent credential =
645 km.createConfirmDeviceCredentialIntent(null, null, userId);
646 // For safety, check null here in case users changed the setting after the checking.
647 if (credential == null) {
650 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
651 if (activityRecord != null) {
652 final IIntentSender target = mService.getIntentSenderLocked(
653 ActivityManager.INTENT_SENDER_ACTIVITY,
654 activityRecord.launchedFromPackage,
655 activityRecord.launchedFromUid,
656 activityRecord.userId,
658 new Intent[] { activityRecord.intent },
659 new String[] { activityRecord.resolvedType },
660 PendingIntent.FLAG_CANCEL_CURRENT |
661 PendingIntent.FLAG_ONE_SHOT |
662 PendingIntent.FLAG_IMMUTABLE,
664 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
665 // Show confirm credentials activity.
666 startConfirmCredentialIntent(credential);
670 void startConfirmCredentialIntent(Intent intent) {
671 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
672 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
673 FLAG_ACTIVITY_TASK_ON_HOME);
674 final ActivityOptions options = ActivityOptions.makeBasic();
675 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
676 mService.mContext.startActivityAsUser(intent, options.toBundle(),
680 final int startActivityMayWait(IApplicationThread caller, int callingUid,
681 String callingPackage, Intent intent, String resolvedType,
682 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
683 IBinder resultTo, String resultWho, int requestCode, int startFlags,
684 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
685 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
686 IActivityContainer iContainer, TaskRecord inTask) {
687 // Refuse possible leaked file descriptors
688 if (intent != null && intent.hasFileDescriptors()) {
689 throw new IllegalArgumentException("File descriptors passed in Intent");
691 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
692 boolean componentSpecified = intent.getComponent() != null;
694 // Save a copy in case ephemeral needs it
695 final Intent ephemeralIntent = new Intent(intent);
696 // Don't modify the client's object!
697 intent = new Intent(intent);
699 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
701 UserInfo userInfo = mSupervisor.getUserInfo(userId);
702 if (userInfo != null && userInfo.isManagedProfile()) {
703 // Special case for managed profiles, if attempting to launch non-cryto aware
704 // app in a locked managed profile from an unlocked parent allow it to resolve
705 // as user will be sent via confirm credentials to unlock the profile.
706 UserManager userManager = UserManager.get(mService.mContext);
707 boolean profileLockedAndParentUnlockingOrUnlocked = false;
708 long token = Binder.clearCallingIdentity();
710 UserInfo parent = userManager.getProfileParent(userId);
711 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
712 && userManager.isUserUnlockingOrUnlocked(parent.id)
713 && !userManager.isUserUnlockingOrUnlocked(userId);
715 Binder.restoreCallingIdentity(token);
717 if (profileLockedAndParentUnlockingOrUnlocked) {
718 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
719 PackageManager.MATCH_DIRECT_BOOT_AWARE
720 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
724 // Collect information about the target of the Intent.
725 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
727 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
728 ActivityStackSupervisor.ActivityContainer container =
729 (ActivityStackSupervisor.ActivityContainer)iContainer;
730 synchronized (mService) {
731 if (container != null && container.mParentActivity != null &&
732 container.mParentActivity.state != RESUMED) {
733 // Cannot start a child activity if the parent is not resumed.
734 return ActivityManager.START_CANCELED;
736 final int realCallingPid = Binder.getCallingPid();
737 final int realCallingUid = Binder.getCallingUid();
739 if (callingUid >= 0) {
741 } else if (caller == null) {
742 callingPid = realCallingPid;
743 callingUid = realCallingUid;
745 callingPid = callingUid = -1;
748 final ActivityStack stack;
749 if (container == null || container.mStack.isOnHomeDisplay()) {
750 stack = mSupervisor.mFocusedStack;
752 stack = container.mStack;
754 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
755 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
756 "Starting activity when config will change = " + stack.mConfigWillChange);
758 final long origId = Binder.clearCallingIdentity();
761 (aInfo.applicationInfo.privateFlags
762 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
763 // This may be a heavy-weight process! Check to see if we already
764 // have another, different heavy-weight process running.
765 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
766 final ProcessRecord heavy = mService.mHeavyWeightProcess;
767 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
768 || !heavy.processName.equals(aInfo.processName))) {
769 int appCallingUid = callingUid;
770 if (caller != null) {
771 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
772 if (callerApp != null) {
773 appCallingUid = callerApp.info.uid;
775 Slog.w(TAG, "Unable to find app for caller " + caller
776 + " (pid=" + callingPid + ") when starting: "
777 + intent.toString());
778 ActivityOptions.abort(options);
779 return ActivityManager.START_PERMISSION_DENIED;
783 IIntentSender target = mService.getIntentSenderLocked(
784 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
785 appCallingUid, userId, null, null, 0, new Intent[] { intent },
786 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
787 | PendingIntent.FLAG_ONE_SHOT, null);
789 Intent newIntent = new Intent();
790 if (requestCode >= 0) {
791 // Caller is requesting a result.
792 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
794 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
795 new IntentSender(target));
796 if (heavy.activities.size() > 0) {
797 ActivityRecord hist = heavy.activities.get(0);
798 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
800 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
803 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
805 newIntent.setFlags(intent.getFlags());
806 newIntent.setClassName("android",
807 HeavyWeightSwitcherActivity.class.getName());
811 callingUid = Binder.getCallingUid();
812 callingPid = Binder.getCallingPid();
813 componentSpecified = true;
814 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
815 aInfo = rInfo != null ? rInfo.activityInfo : null;
817 aInfo = mService.getActivityInfoForUser(aInfo, userId);
823 final ActivityRecord[] outRecord = new ActivityRecord[1];
824 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
825 aInfo, rInfo, voiceSession, voiceInteractor,
826 resultTo, resultWho, requestCode, callingPid,
827 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
828 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
831 Binder.restoreCallingIdentity(origId);
833 if (stack.mConfigWillChange) {
834 // If the caller also wants to switch to a new configuration,
835 // do so now. This allows a clean switch, as we are waiting
836 // for the current activity to pause (so we will not destroy
837 // it), and have not yet started the next activity.
838 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
839 "updateConfiguration()");
840 stack.mConfigWillChange = false;
841 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
842 "Updating to new configuration after starting activity.");
843 mService.updateConfigurationLocked(config, null, false);
846 if (outResult != null) {
847 outResult.result = res;
848 if (res == ActivityManager.START_SUCCESS) {
849 mSupervisor.mWaitingActivityLaunched.add(outResult);
853 } catch (InterruptedException e) {
855 } while (outResult.result != START_TASK_TO_FRONT
856 && !outResult.timeout && outResult.who == null);
857 if (outResult.result == START_TASK_TO_FRONT) {
858 res = START_TASK_TO_FRONT;
861 if (res == START_TASK_TO_FRONT) {
862 ActivityRecord r = stack.topRunningActivityLocked();
863 if (r.nowVisible && r.state == RESUMED) {
864 outResult.timeout = false;
865 outResult.who = new ComponentName(r.info.packageName, r.info.name);
866 outResult.totalTime = 0;
867 outResult.thisTime = 0;
869 outResult.thisTime = SystemClock.uptimeMillis();
870 mSupervisor.mWaitingActivityVisible.add(outResult);
874 } catch (InterruptedException e) {
876 } while (!outResult.timeout && outResult.who == null);
881 final ActivityRecord launchedActivity = mReusedActivity != null
882 ? mReusedActivity : outRecord[0];
883 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
888 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
889 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
890 Bundle bOptions, int userId) {
891 if (intents == null) {
892 throw new NullPointerException("intents is null");
894 if (resolvedTypes == null) {
895 throw new NullPointerException("resolvedTypes is null");
897 if (intents.length != resolvedTypes.length) {
898 throw new IllegalArgumentException("intents are length different than resolvedTypes");
903 if (callingUid >= 0) {
905 } else if (caller == null) {
906 callingPid = Binder.getCallingPid();
907 callingUid = Binder.getCallingUid();
909 callingPid = callingUid = -1;
911 final long origId = Binder.clearCallingIdentity();
913 synchronized (mService) {
914 ActivityRecord[] outActivity = new ActivityRecord[1];
915 for (int i=0; i<intents.length; i++) {
916 Intent intent = intents[i];
917 if (intent == null) {
921 // Refuse possible leaked file descriptors
922 if (intent != null && intent.hasFileDescriptors()) {
923 throw new IllegalArgumentException("File descriptors passed in Intent");
926 boolean componentSpecified = intent.getComponent() != null;
928 // Don't modify the client's object!
929 intent = new Intent(intent);
931 // Collect information about the target of the Intent.
932 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
934 // TODO: New, check if this is correct
935 aInfo = mService.getActivityInfoForUser(aInfo, userId);
938 (aInfo.applicationInfo.privateFlags
939 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
940 throw new IllegalArgumentException(
941 "FLAG_CANT_SAVE_STATE not supported here");
944 ActivityOptions options = ActivityOptions.fromBundle(
945 i == intents.length - 1 ? bOptions : null);
946 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
947 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
948 callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
949 options, false, componentSpecified, outActivity, null, null);
954 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
958 Binder.restoreCallingIdentity(origId);
961 return START_SUCCESS;
964 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
965 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
966 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
968 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
971 computeLaunchingTaskFlags();
973 computeSourceStack();
975 mIntent.setFlags(mLaunchFlags);
977 mReusedActivity = getReusableIntentActivity();
979 final int preferredLaunchStackId =
980 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
982 if (mReusedActivity != null) {
983 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
984 // still needs to be a lock task mode violation since the task gets cleared out and
985 // the device would otherwise leave the locked task.
986 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
987 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
988 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
989 mSupervisor.showLockTaskToast();
990 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
991 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
994 if (mStartActivity.task == null) {
995 mStartActivity.task = mReusedActivity.task;
997 if (mReusedActivity.task.intent == null) {
998 // This task was started because of movement of the activity based on affinity...
999 // Now that we are actually launching it, we can assign the base intent.
1000 mReusedActivity.task.setIntent(mStartActivity);
1003 // This code path leads to delivering a new intent, we want to make sure we schedule it
1004 // as the first operation, in case the activity will be resumed as a result of later
1006 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1007 || mLaunchSingleInstance || mLaunchSingleTask) {
1008 // In this situation we want to remove all activities from the task up to the one
1009 // being started. In most cases this means we are resetting the task to its initial
1011 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
1012 mStartActivity, mLaunchFlags);
1014 if (top.frontOfTask) {
1015 // Activity aliases may mean we use different intents for the top activity,
1016 // so make sure the task now has the identity of the new intent.
1017 top.task.setIntent(mStartActivity);
1019 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1020 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1021 mStartActivity.launchedFromPackage);
1025 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
1027 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1028 // We don't need to start a new activity, and the client said not to do anything
1029 // if that is the case, so this is it! And for paranoia, make sure we have
1030 // correctly resumed the top activity.
1031 resumeTargetStackIfNeeded();
1032 return START_RETURN_INTENT_TO_CALLER;
1034 setTaskFromIntentActivity(mReusedActivity);
1036 if (!mAddingToTask && mReuseTask == null) {
1037 // We didn't do anything... but it was needed (a.k.a., client don't use that
1038 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1039 resumeTargetStackIfNeeded();
1040 return START_TASK_TO_FRONT;
1044 if (mStartActivity.packageName == null) {
1045 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1046 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1047 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1048 mStartActivity.requestCode, RESULT_CANCELED, null);
1050 ActivityOptions.abort(mOptions);
1051 return START_CLASS_NOT_FOUND;
1054 // If the activity being launched is the same as the one currently at the top, then
1055 // we need to check if it should only be launched once.
1056 final ActivityStack topStack = mSupervisor.mFocusedStack;
1057 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1058 final boolean dontStart = top != null && mStartActivity.resultTo == null
1059 && top.realActivity.equals(mStartActivity.realActivity)
1060 && top.userId == mStartActivity.userId
1061 && top.app != null && top.app.thread != null
1062 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1063 || mLaunchSingleTop || mLaunchSingleTask);
1065 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1066 // For paranoia, make sure we have correctly resumed the top activity.
1067 topStack.mLastPausedActivity = null;
1069 mSupervisor.resumeFocusedStackTopActivityLocked();
1071 ActivityOptions.abort(mOptions);
1072 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1073 // We don't need to start a new activity, and the client said not to do
1074 // anything if that is the case, so this is it!
1075 return START_RETURN_INTENT_TO_CALLER;
1077 top.deliverNewIntentLocked(
1078 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1080 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1081 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1082 mSupervisor.handleNonResizableTaskIfNeeded(
1083 top.task, preferredLaunchStackId, topStack.mStackId);
1085 return START_DELIVERED_TO_TOP;
1088 boolean newTask = false;
1089 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1090 ? mSourceRecord.task : null;
1092 // Should this be considered a new task?
1093 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1094 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1096 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1098 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1099 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1100 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1102 if (!mMovedOtherTask) {
1103 updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
1105 } else if (mSourceRecord != null) {
1106 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1107 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1108 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1111 final int result = setTaskFromSourceRecord();
1112 if (result != START_SUCCESS) {
1115 } else if (mInTask != null) {
1116 // The caller is asking that the new activity be started in an explicit
1117 // task it has provided to us.
1118 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1119 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1120 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1123 final int result = setTaskFromInTask();
1124 if (result != START_SUCCESS) {
1128 // This not being started from an existing activity, and not part of a new task...
1129 // just put it in the top task, though these days this case should never happen.
1130 setTaskToCurrentTopOrCreateNewTask();
1133 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1134 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1136 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1137 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1140 EventLog.writeEvent(
1141 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1143 ActivityStack.logStartActivity(
1144 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1145 mTargetStack.mLastPausedActivity = null;
1146 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1148 if (!mLaunchTaskBehind) {
1149 // TODO(b/26381750): Remove this code after verification that all the decision
1150 // points above moved targetStack to the front which will also set the focus
1152 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1154 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1155 if (!mTargetStack.isFocusable()
1156 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1157 && mStartActivity != topTaskActivity)) {
1158 // If the activity is not focusable, we can't resume it, but still would like to
1159 // make sure it becomes visible as it starts (this will also trigger entry
1160 // animation). An example of this are PIP activities.
1161 // Also, we don't want to resume activities in a task that currently has an overlay
1162 // as the starting activity just needs to be in the visible paused state until the
1164 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1165 // Go ahead and tell window manager to execute app transition for this activity
1166 // since the app transition will not be triggered through the resume channel.
1167 mWindowManager.executeAppTransition();
1169 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1173 mTargetStack.addRecentActivityLocked(mStartActivity);
1175 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1177 mSupervisor.handleNonResizableTaskIfNeeded(
1178 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
1180 return START_SUCCESS;
1183 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1184 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1185 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1191 mCallingUid = r.launchedFromUid;
1192 mSourceRecord = sourceRecord;
1193 mVoiceSession = voiceSession;
1194 mVoiceInteractor = voiceInteractor;
1196 mLaunchBounds = getOverrideBounds(r, options, inTask);
1198 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1199 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1200 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1201 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1202 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1203 mLaunchTaskBehind = r.mLaunchTaskBehind
1204 && !mLaunchSingleTask && !mLaunchSingleInstance
1205 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1207 sendNewTaskResultRequestIfNeeded();
1209 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1210 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1213 // If we are actually going to launch in to a new task, there are some cases where
1214 // we further want to do multiple task.
1215 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1216 if (mLaunchTaskBehind
1217 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1218 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1222 // We'll invoke onUserLeaving before onPause only if the launching
1223 // activity did not explicitly state that this is an automated launch.
1224 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1225 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1226 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1228 // If the caller has asked not to resume at this point, we make note
1229 // of this in the record so that we can skip it when trying to find
1230 // the top running activity.
1231 mDoResume = doResume;
1232 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1233 r.delayedResume = true;
1237 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1238 r.mTaskOverlay = true;
1239 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1240 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1241 if (top != null && !top.visible) {
1243 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1246 mAvoidMoveToFront = true;
1250 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1253 // In some flows in to this function, we retrieve the task record and hold on to it
1254 // without a lock before calling back in to here... so the task at this point may
1255 // not actually be in recents. Check for that, and if it isn't in recents just
1256 // consider it invalid.
1257 if (inTask != null && !inTask.inRecents) {
1258 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1262 mStartFlags = startFlags;
1263 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1264 // is the same as the one making the call... or, as a special case, if we do not know
1265 // the caller then we count the current top activity as the caller.
1266 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1267 ActivityRecord checkedCaller = sourceRecord;
1268 if (checkedCaller == null) {
1269 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1272 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1273 // Caller is not the same as launcher, so always needed.
1274 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1278 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1281 private void sendNewTaskResultRequestIfNeeded() {
1282 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1283 && mStartActivity.resultTo.task.stack != null) {
1284 // For whatever reason this activity is being launched into a new task...
1285 // yet the caller has requested a result back. Well, that is pretty messed up,
1286 // so instead immediately send back a cancel and let the new task continue launched
1287 // as normal without a dependency on its originator.
1288 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1289 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1290 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1291 mStartActivity.resultTo = null;
1295 private void computeLaunchingTaskFlags() {
1296 // If the caller is not coming from another activity, but has given us an explicit task into
1297 // which they would like us to launch the new activity, then let's see about doing that.
1298 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1299 final Intent baseIntent = mInTask.getBaseIntent();
1300 final ActivityRecord root = mInTask.getRootActivity();
1301 if (baseIntent == null) {
1302 ActivityOptions.abort(mOptions);
1303 throw new IllegalArgumentException("Launching into task without base intent: "
1307 // If this task is empty, then we are adding the first activity -- it
1308 // determines the root, and must be launching as a NEW_TASK.
1309 if (mLaunchSingleInstance || mLaunchSingleTask) {
1310 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1311 ActivityOptions.abort(mOptions);
1312 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1313 + mStartActivity + " into different task " + mInTask);
1316 ActivityOptions.abort(mOptions);
1317 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1318 + " has root " + root + " but target is singleInstance/Task");
1322 // If task is empty, then adopt the interesting intent launch flags in to the
1323 // activity being started.
1325 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1326 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1327 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1328 | (baseIntent.getFlags() & flagsOfInterest);
1329 mIntent.setFlags(mLaunchFlags);
1330 mInTask.setIntent(mStartActivity);
1331 mAddingToTask = true;
1333 // If the task is not empty and the caller is asking to start it as the root of
1334 // a new task, then we don't actually want to start this on the task. We will
1335 // bring the task to the front, and possibly give it a new intent.
1336 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1337 mAddingToTask = false;
1340 mAddingToTask = true;
1343 mReuseTask = mInTask;
1346 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1347 // when in freeform workspace.
1348 // Also put noDisplay activities in the source task. These by itself can be placed
1349 // in any task/stack, however it could launch other activities like ResolverActivity,
1350 // and we want those to stay in the original task.
1351 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1352 && mSourceRecord.isFreeform()) {
1353 mAddingToTask = true;
1357 if (mInTask == null) {
1358 if (mSourceRecord == null) {
1359 // This activity is not being started from another... in this
1360 // case we -always- start a new task.
1361 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1362 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1363 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1364 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1366 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1367 // The original activity who is starting us is running as a single
1368 // instance... this new activity it is starting must go on its
1370 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1371 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1372 // The activity being started is a single instance... it always
1373 // gets launched into its own task.
1374 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1379 private void computeSourceStack() {
1380 if (mSourceRecord == null) {
1381 mSourceStack = null;
1384 if (!mSourceRecord.finishing) {
1385 mSourceStack = mSourceRecord.task.stack;
1389 // If the source is finishing, we can't further count it as our source. This is because the
1390 // task it is associated with may now be empty and on its way out, so we don't want to
1391 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1392 // a task for it. But save the task information so it can be used when creating the new task.
1393 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1394 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1395 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1396 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1397 mNewTaskInfo = mSourceRecord.info;
1398 mNewTaskIntent = mSourceRecord.task.intent;
1400 mSourceRecord = null;
1401 mSourceStack = null;
1405 * Decide whether the new activity should be inserted into an existing task. Returns null
1406 * if not or an ActivityRecord with the task into which the new activity should be added.
1408 private ActivityRecord getReusableIntentActivity() {
1409 // We may want to try to place the new activity in to an existing task. We always
1410 // do this if the target activity is singleTask or singleInstance; we will also do
1411 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1412 // us to still place it in a new task: multi task, always doc mode, or being asked to
1413 // launch this as a new task behind the current one.
1414 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1415 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1416 || mLaunchSingleInstance || mLaunchSingleTask;
1417 // If bring to front is requested, and no result is requested and we have not been given
1418 // an explicit task to launch in to, and we can find a task that was started with this
1419 // same component, then instead of launching bring that one to the front.
1420 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1421 ActivityRecord intentActivity = null;
1422 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1423 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1424 intentActivity = task != null ? task.getTopActivity() : null;
1425 } else if (putIntoExistingTask) {
1426 if (mLaunchSingleInstance) {
1427 // There can be one and only one instance of single instance activity in the
1428 // history, and it is always in its own unique task, so we do a special search.
1429 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
1430 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1431 // For the launch adjacent case we only want to put the activity in an existing
1432 // task if the activity already exists in the history.
1433 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1434 !mLaunchSingleTask);
1436 // Otherwise find the best task to put the activity in.
1437 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1440 return intentActivity;
1443 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1444 mTargetStack = intentActivity.task.stack;
1445 mTargetStack.mLastPausedActivity = null;
1446 // If the target task is not in the front, then we need to bring it to the front...
1447 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1448 // the same behavior as if a new instance was being started, which means not bringing it
1449 // to the front if the caller is not itself in the front.
1450 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1451 ActivityRecord curTop = (focusStack == null)
1452 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1455 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1456 && !mAvoidMoveToFront) {
1457 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1458 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1459 mSourceStack.topActivity().task == mSourceRecord.task)) {
1460 // We really do want to push this one into the user's face, right now.
1461 if (mLaunchTaskBehind && mSourceRecord != null) {
1462 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1464 mMovedOtherTask = true;
1466 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1467 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1468 // So no point resuming any of the activities here, it just wastes one extra
1469 // resuming, plus enter AND exit transitions.
1470 // Here we only want to bring the target stack forward. Transition will be applied
1471 // to the new activity that's started after the old ones are gone.
1472 final boolean willClearTask =
1473 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1474 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1475 if (!willClearTask) {
1476 final ActivityStack launchStack = getLaunchStack(
1477 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
1478 if (launchStack == null || launchStack == mTargetStack) {
1479 // We only want to move to the front, if we aren't going to launch on a
1480 // different stack. If we launch on a different stack, we will put the
1481 // task on top there.
1482 mTargetStack.moveTaskToFrontLocked(
1483 intentActivity.task, mNoAnimation, mOptions,
1484 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1485 mMovedToFront = true;
1486 } else if (launchStack.mStackId == DOCKED_STACK_ID
1487 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1488 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1489 // If we want to launch adjacent and mTargetStack is not the computed
1490 // launch stack - move task to top of computed stack.
1491 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1492 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1495 // TODO: This should be reevaluated in MW v2.
1496 // We choose to move task to front instead of launching it adjacent
1497 // when specific stack was requested explicitly and it appeared to be
1498 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1499 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1500 mOptions, mStartActivity.appTimeTracker,
1501 "bringToFrontInsteadOfAdjacentLaunch");
1503 mMovedToFront = true;
1507 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
1510 if (!mMovedToFront && mDoResume) {
1511 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1512 + " from " + intentActivity);
1513 mTargetStack.moveToFront("intentActivityFound");
1516 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1517 mTargetStack.mStackId);
1519 // If the caller has requested that the target task be reset, then do so.
1520 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1521 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1523 return intentActivity;
1526 private void updateTaskReturnToType(
1527 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1528 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1529 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1530 // Caller wants to appear on home activity.
1531 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1533 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1534 // Task will be launched over the home stack, so return home.
1535 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1539 // Else we are coming from an application stack so return to an application.
1540 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1543 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1544 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1545 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1546 // The caller has requested to completely replace any existing task with its new
1547 // activity. Well that should not be too hard...
1548 mReuseTask = intentActivity.task;
1549 mReuseTask.performClearTaskLocked();
1550 mReuseTask.setIntent(mStartActivity);
1551 // When we clear the task - focus will be adjusted, which will bring another task
1552 // to top before we launch the activity we need. This will temporary swap their
1553 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1554 mMovedOtherTask = true;
1555 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1556 || mLaunchSingleInstance || mLaunchSingleTask) {
1557 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1560 // A special case: we need to start the activity because it is not currently
1561 // running, and the caller has asked to clear the current task to have this
1562 // activity at the top.
1563 mAddingToTask = true;
1564 // Now pretend like this activity is being started by the top of its task, so it
1565 // is put in the right place.
1566 mSourceRecord = intentActivity;
1567 final TaskRecord task = mSourceRecord.task;
1568 if (task != null && task.stack == null) {
1569 // Target stack got cleared when we all activities were removed above.
1570 // Go ahead and reset it.
1571 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1572 null /* bounds */, mLaunchFlags, mOptions);
1573 mTargetStack.addTask(task,
1574 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1577 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1578 // In this case the top activity on the task is the same as the one being launched,
1579 // so we take that as a request to bring the task to the foreground. If the top
1580 // activity in the task is the root activity, deliver this new intent to it if it
1582 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1583 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1584 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1585 intentActivity.task);
1586 if (intentActivity.frontOfTask) {
1587 intentActivity.task.setIntent(mStartActivity);
1589 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1590 mStartActivity.launchedFromPackage);
1591 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
1592 // In this case we are launching the root activity of the task, but with a
1593 // different intent. We should start a new instance on top.
1594 mAddingToTask = true;
1595 mSourceRecord = intentActivity;
1597 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1598 // In this case an activity is being launched in to an existing task, without
1599 // resetting that task. This is typically the situation of launching an activity
1600 // from a notification or shortcut. We want to place the new activity on top of the
1602 mAddingToTask = true;
1603 mSourceRecord = intentActivity;
1604 } else if (!intentActivity.task.rootWasReset) {
1605 // In this case we are launching into an existing task that has not yet been started
1606 // from its front door. The current task has been brought to the front. Ideally,
1607 // we'd probably like to place this new task at the bottom of its stack, but that's
1608 // a little hard to do with the current organization of the code so for now we'll
1610 intentActivity.task.setIntent(mStartActivity);
1614 private void resumeTargetStackIfNeeded() {
1616 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1617 if (!mMovedToFront) {
1618 // Make sure to notify Keyguard as well if we are not running an app transition
1620 mSupervisor.notifyActivityDrawnForKeyguard();
1623 ActivityOptions.abort(mOptions);
1625 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1628 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1629 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1632 if (mReuseTask == null) {
1633 final TaskRecord task = mTargetStack.createTaskRecord(
1634 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1635 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1636 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1637 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1638 mStartActivity.setTask(task, taskToAffiliate);
1639 if (mLaunchBounds != null) {
1640 final int stackId = mTargetStack.mStackId;
1641 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1642 mService.resizeStack(
1643 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1645 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1648 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1649 "Starting new activity " +
1650 mStartActivity + " in new task " + mStartActivity.task);
1652 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1656 private int setTaskFromSourceRecord() {
1657 final TaskRecord sourceTask = mSourceRecord.task;
1658 // We only want to allow changing stack if the target task is not the top one,
1659 // otherwise we would move the launching task to the other side, rather than show
1660 // two side by side.
1661 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1662 if (moveStackAllowed) {
1663 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1667 if (mTargetStack == null) {
1668 mTargetStack = sourceTask.stack;
1669 } else if (mTargetStack != sourceTask.stack) {
1670 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1671 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1674 mTargetStack.moveToFront("sourceStackToFront");
1676 final TaskRecord topTask = mTargetStack.topTask();
1677 if (topTask != sourceTask && !mAvoidMoveToFront) {
1678 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1679 mStartActivity.appTimeTracker, "sourceTaskToFront");
1681 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1682 // In this case, we are adding the activity to an existing task, but the caller has
1683 // asked to clear that task if the activity is already running.
1684 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1685 mKeepCurTransition = true;
1687 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1688 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1689 // For paranoia, make sure we have correctly resumed the top activity.
1690 mTargetStack.mLastPausedActivity = null;
1692 mSupervisor.resumeFocusedStackTopActivityLocked();
1694 ActivityOptions.abort(mOptions);
1695 return START_DELIVERED_TO_TOP;
1697 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1698 // In this case, we are launching an activity in our own task that may already be
1699 // running somewhere in the history, and we want to shuffle it to the front of the
1701 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1703 final TaskRecord task = top.task;
1704 task.moveActivityToFrontLocked(top);
1705 top.updateOptionsLocked(mOptions);
1706 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1707 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1708 mTargetStack.mLastPausedActivity = null;
1710 mSupervisor.resumeFocusedStackTopActivityLocked();
1712 return START_DELIVERED_TO_TOP;
1716 // An existing activity is starting this new activity, so we want to keep the new one in
1717 // the same task as the one that is starting it.
1718 mStartActivity.setTask(sourceTask, null);
1719 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1720 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1721 return START_SUCCESS;
1724 private int setTaskFromInTask() {
1725 if (mLaunchBounds != null) {
1726 mInTask.updateOverrideConfiguration(mLaunchBounds);
1727 int stackId = mInTask.getLaunchStackId();
1728 if (stackId != mInTask.stack.mStackId) {
1729 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
1730 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1731 stackId = stack.mStackId;
1733 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1734 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1737 mTargetStack = mInTask.stack;
1738 mTargetStack.moveTaskToFrontLocked(
1739 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1741 // Check whether we should actually launch the new activity in to the task,
1742 // or just reuse the current activity on top.
1743 ActivityRecord top = mInTask.getTopActivity();
1744 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1745 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1746 || mLaunchSingleTop || mLaunchSingleTask) {
1747 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1748 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1749 // We don't need to start a new activity, and the client said not to do
1750 // anything if that is the case, so this is it!
1751 return START_RETURN_INTENT_TO_CALLER;
1753 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1754 return START_DELIVERED_TO_TOP;
1758 if (!mAddingToTask) {
1759 // We don't actually want to have this activity added to the task, so just
1760 // stop here but still tell the caller that we consumed the intent.
1761 ActivityOptions.abort(mOptions);
1762 return START_TASK_TO_FRONT;
1765 mStartActivity.setTask(mInTask, null);
1766 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1767 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1769 return START_SUCCESS;
1772 private void setTaskToCurrentTopOrCreateNewTask() {
1773 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1776 mTargetStack.moveToFront("addingToTopTask");
1778 final ActivityRecord prev = mTargetStack.topActivity();
1779 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1780 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1781 mStartActivity.info, mIntent, null, null, true);
1782 mStartActivity.setTask(task, null);
1783 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1784 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1785 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1788 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1789 boolean launchSingleTask, int launchFlags) {
1790 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1791 (launchSingleInstance || launchSingleTask)) {
1792 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1793 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1794 "\"singleInstance\" or \"singleTask\"");
1796 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1798 switch (r.info.documentLaunchMode) {
1799 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1801 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1802 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1804 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1805 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1807 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1808 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1815 final void doPendingActivityLaunchesLocked(boolean doResume) {
1816 while (!mPendingActivityLaunches.isEmpty()) {
1817 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1818 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
1820 final int result = startActivityUnchecked(
1821 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1822 postStartActivityUncheckedProcessing(
1823 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1825 } catch (Exception e) {
1826 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1827 pal.sendErrorResult(e.getMessage());
1832 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1833 int launchFlags, ActivityOptions aOptions) {
1834 final TaskRecord task = r.task;
1835 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1836 return mSupervisor.mHomeStack;
1839 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
1840 if (stack != null) {
1844 if (task != null && task.stack != null) {
1846 if (stack.isOnHomeDisplay()) {
1847 if (mSupervisor.mFocusedStack != stack) {
1848 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1849 "computeStackFocus: Setting " + "focused stack to r=" + r
1852 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1853 "computeStackFocus: Focused stack already="
1854 + mSupervisor.mFocusedStack);
1860 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1861 if (container != null) {
1862 // The first time put it on the desired stack, after this put on task stack.
1863 r.mInitialActivityContainer = null;
1864 return container.mStack;
1867 // The fullscreen stack can contain any task regardless of if the task is resizeable
1868 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1869 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1870 // we can also put it in the focused stack.
1871 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1872 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1873 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1874 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
1875 if (canUseFocusedStack && (!newTask
1876 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1877 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1878 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1879 return mSupervisor.mFocusedStack;
1882 // We first try to put the task in the first dynamic stack.
1883 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1884 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1885 stack = homeDisplayStacks.get(stackNdx);
1886 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1887 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1888 "computeStackFocus: Setting focused stack=" + stack);
1893 // If there is no suitable dynamic stack then we figure out which static stack to use.
1894 final int stackId = task != null ? task.getLaunchStackId() :
1895 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1896 FULLSCREEN_WORKSPACE_STACK_ID;
1897 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1898 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1899 + r + " stackId=" + stack.mStackId);
1903 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1904 ActivityOptions aOptions) {
1906 // We are reusing a task, keep the stack!
1907 if (mReuseTask != null) {
1908 return mReuseTask.stack;
1911 final int launchStackId =
1912 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1914 if (isValidLaunchStackId(launchStackId, r)) {
1915 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
1916 } else if (launchStackId == DOCKED_STACK_ID) {
1917 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1918 // for this activity, so we put the activity in the fullscreen stack.
1919 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1922 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
1925 // Otherwise handle adjacent launch.
1927 // The parent activity doesn't want to launch the activity on top of itself, but
1928 // instead tries to put it onto other side in side-by-side mode.
1929 final ActivityStack parentStack = task != null ? task.stack
1930 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1931 : mSupervisor.mFocusedStack;
1933 if (parentStack != mSupervisor.mFocusedStack) {
1934 // If task's parent stack is not focused - use it during adjacent launch.
1937 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1938 // If task is already on top of focused stack - use it. We don't want to move the
1939 // existing focused task to adjacent stack, just deliver new intent in this case.
1940 return mSupervisor.mFocusedStack;
1943 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1944 // If parent was in docked stack, the natural place to launch another activity
1945 // will be fullscreen, so it can appear alongside the docked window.
1946 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1949 // If the parent is not in the docked stack, we check if there is docked window
1950 // and if yes, we will launch into that stack. If not, we just put the new
1951 // activity into parent's stack, because we can't find a better place.
1952 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
1953 if (dockedStack != null
1954 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
1955 // There is a docked stack, but it isn't visible, so we can't launch into that.
1964 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1965 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1966 || !StackId.isStaticStack(stackId)) {
1970 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
1971 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
1975 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
1979 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1983 final boolean supportsPip = mService.mSupportsPictureInPicture
1984 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1985 if (stackId == PINNED_STACK_ID && !supportsPip) {
1991 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1992 Rect newBounds = null;
1993 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
1994 if (mSupervisor.canUseActivityOptionsLaunchBounds(
1995 options, options.getLaunchStackId())) {
1996 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2002 void setWindowManager(WindowManagerService wm) {
2003 mWindowManager = wm;
2006 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2007 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2008 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2009 if (pal.stack == stack) {
2010 mPendingActivityLaunches.remove(palNdx);