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.RemoteException;
107 import android.os.SystemClock;
108 import android.os.UserHandle;
109 import android.os.UserManager;
110 import android.service.voice.IVoiceInteractionSession;
111 import android.util.EventLog;
112 import android.util.Slog;
113 import android.view.Display;
115 import com.android.internal.app.HeavyWeightSwitcherActivity;
116 import com.android.internal.app.IVoiceInteractor;
117 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
118 import com.android.server.wm.WindowManagerService;
120 import java.util.ArrayList;
123 * Controller for interpreting how and then launching activities.
125 * This class collects all the logic for determining how an intent and flags should be turned into
126 * an activity and associated task and stack.
128 class ActivityStarter {
129 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
130 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
131 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
132 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
133 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
135 private final ActivityManagerService mService;
136 private final ActivityStackSupervisor mSupervisor;
137 private ActivityStartInterceptor mInterceptor;
138 private WindowManagerService mWindowManager;
140 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
142 // Share state variable among methods when starting an activity.
143 private ActivityRecord mStartActivity;
144 private ActivityRecord mReusedActivity;
145 private Intent mIntent;
146 private int mCallingUid;
147 private ActivityOptions mOptions;
149 private boolean mLaunchSingleTop;
150 private boolean mLaunchSingleInstance;
151 private boolean mLaunchSingleTask;
152 private boolean mLaunchTaskBehind;
153 private int mLaunchFlags;
155 private Rect mLaunchBounds;
157 private ActivityRecord mNotTop;
158 private boolean mDoResume;
159 private int mStartFlags;
160 private ActivityRecord mSourceRecord;
162 private TaskRecord mInTask;
163 private boolean mAddingToTask;
164 private TaskRecord mReuseTask;
166 private ActivityInfo mNewTaskInfo;
167 private Intent mNewTaskIntent;
168 private ActivityStack mSourceStack;
169 private ActivityStack mTargetStack;
170 // Indicates that we moved other task and are going to put something on top soon, so
171 // we don't want to show it redundantly or accidentally change what's shown below.
172 private boolean mMovedOtherTask;
173 private boolean mMovedToFront;
174 private boolean mNoAnimation;
175 private boolean mKeepCurTransition;
176 private boolean mAvoidMoveToFront;
177 private boolean mPowerHintSent;
179 private IVoiceInteractionSession mVoiceSession;
180 private IVoiceInteractor mVoiceInteractor;
182 private void reset() {
183 mStartActivity = null;
188 mLaunchSingleTop = false;
189 mLaunchSingleInstance = false;
190 mLaunchSingleTask = false;
191 mLaunchTaskBehind = false;
194 mLaunchBounds = null;
199 mSourceRecord = null;
202 mAddingToTask = false;
206 mNewTaskIntent = null;
210 mMovedOtherTask = false;
211 mMovedToFront = false;
212 mNoAnimation = false;
213 mKeepCurTransition = false;
214 mAvoidMoveToFront = false;
216 mVoiceSession = null;
217 mVoiceInteractor = null;
220 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
222 mSupervisor = supervisor;
223 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
226 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
227 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
228 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
229 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
230 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
231 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
232 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
234 int err = ActivityManager.START_SUCCESS;
236 ProcessRecord callerApp = null;
237 if (caller != null) {
238 callerApp = mService.getRecordForAppLocked(caller);
239 if (callerApp != null) {
240 callingPid = callerApp.pid;
241 callingUid = callerApp.info.uid;
243 Slog.w(TAG, "Unable to find app for caller " + caller
244 + " (pid=" + callingPid + ") when starting: "
245 + intent.toString());
246 err = ActivityManager.START_PERMISSION_DENIED;
250 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
252 if (err == ActivityManager.START_SUCCESS) {
253 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
254 + "} from uid " + callingUid
255 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
256 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
257 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
258 container.mActivityDisplay.mDisplayId)));
261 ActivityRecord sourceRecord = null;
262 ActivityRecord resultRecord = null;
263 if (resultTo != null) {
264 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
265 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
266 "Will send result to " + resultTo + " " + sourceRecord);
267 if (sourceRecord != null) {
268 if (requestCode >= 0 && !sourceRecord.finishing) {
269 resultRecord = sourceRecord;
274 final int launchFlags = intent.getFlags();
276 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
277 // Transfer the result target from the source activity to the new
278 // one being started, including any failures.
279 if (requestCode >= 0) {
280 ActivityOptions.abort(options);
281 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
283 resultRecord = sourceRecord.resultTo;
284 if (resultRecord != null && !resultRecord.isInStackLocked()) {
287 resultWho = sourceRecord.resultWho;
288 requestCode = sourceRecord.requestCode;
289 sourceRecord.resultTo = null;
290 if (resultRecord != null) {
291 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
293 if (sourceRecord.launchedFromUid == callingUid) {
294 // The new activity is being launched from the same uid as the previous
295 // activity in the flow, and asking to forward its result back to the
296 // previous. In this case the activity is serving as a trampoline between
297 // the two, so we also want to update its launchedFromPackage to be the
298 // same as the previous activity. Note that this is safe, since we know
299 // these two packages come from the same uid; the caller could just as
300 // well have supplied that same package name itself. This specifially
301 // deals with the case of an intent picker/chooser being launched in the app
302 // flow to redirect to an activity picked by the user, where we want the final
303 // activity to consider it to have been launched by the previous app activity.
304 callingPackage = sourceRecord.launchedFromPackage;
308 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
309 // We couldn't find a class that can handle the given Intent.
310 // That's the end of that!
311 err = ActivityManager.START_INTENT_NOT_RESOLVED;
314 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
315 // We couldn't find the specific class specified in the Intent.
316 // Also the end of the line.
317 err = ActivityManager.START_CLASS_NOT_FOUND;
320 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
321 && sourceRecord.task.voiceSession != null) {
322 // If this activity is being launched as part of a voice session, we need
323 // to ensure that it is safe to do so. If the upcoming activity will also
324 // be part of the voice session, we can only launch it if it has explicitly
325 // said it supports the VOICE category, or it is a part of the calling app.
326 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
327 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
329 intent.addCategory(Intent.CATEGORY_VOICE);
330 if (!AppGlobals.getPackageManager().activitySupportsIntent(
331 intent.getComponent(), intent, resolvedType)) {
333 "Activity being started in current voice task does not support voice: "
335 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
337 } catch (RemoteException e) {
338 Slog.w(TAG, "Failure checking voice capabilities", e);
339 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
344 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
345 // If the caller is starting a new voice session, just make sure the target
346 // is actually allowing it to run this way.
348 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
349 intent, resolvedType)) {
351 "Activity being started in new voice task does not support: "
353 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
355 } catch (RemoteException e) {
356 Slog.w(TAG, "Failure checking voice capabilities", e);
357 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
361 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
363 if (err != START_SUCCESS) {
364 if (resultRecord != null) {
365 resultStack.sendActivityResultLocked(
366 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
368 ActivityOptions.abort(options);
372 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
373 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
374 resultRecord, resultStack, options);
375 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
376 callingPid, resolvedType, aInfo.applicationInfo);
378 if (mService.mController != null) {
380 // The Intent we give to the watcher has the extra data
381 // stripped off, since it can contain private information.
382 Intent watchIntent = intent.cloneFilter();
383 abort |= !mService.mController.activityStarting(watchIntent,
384 aInfo.applicationInfo.packageName);
385 } catch (RemoteException e) {
386 mService.mController = null;
390 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
391 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
393 intent = mInterceptor.mIntent;
394 rInfo = mInterceptor.mRInfo;
395 aInfo = mInterceptor.mAInfo;
396 resolvedType = mInterceptor.mResolvedType;
397 inTask = mInterceptor.mInTask;
398 callingPid = mInterceptor.mCallingPid;
399 callingUid = mInterceptor.mCallingUid;
400 options = mInterceptor.mActivityOptions;
402 if (resultRecord != null) {
403 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
404 RESULT_CANCELED, null);
406 // We pretend to the caller that it was really started, but
407 // they will just get a cancel result.
408 ActivityOptions.abort(options);
409 return START_SUCCESS;
412 // If permissions need a review before any of the app components can run, we
413 // launch the review activity and pass a pending intent to start the activity
414 // we are to launching now after the review is completed.
415 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
416 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
417 aInfo.packageName, userId)) {
418 IIntentSender target = mService.getIntentSenderLocked(
419 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
420 callingUid, userId, null, null, 0, new Intent[]{intent},
421 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
422 | PendingIntent.FLAG_ONE_SHOT, null);
424 final int flags = intent.getFlags();
425 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
426 newIntent.setFlags(flags
427 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
428 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
429 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
430 if (resultRecord != null) {
431 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
436 callingUid = realCallingUid;
437 callingPid = realCallingPid;
439 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
440 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
441 null /*profilerInfo*/);
443 if (DEBUG_PERMISSIONS_REVIEW) {
444 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
445 true, false) + "} from uid " + callingUid + " on display "
446 + (container == null ? (mSupervisor.mFocusedStack == null ?
447 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
448 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
449 container.mActivityDisplay.mDisplayId)));
454 // If we have an ephemeral app, abort the process of launching the resolved intent.
455 // Instead, launch the ephemeral installer. Once the installer is finished, it
456 // starts either the intent we resolved here [on install error] or the ephemeral
457 // app [on install success].
458 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
459 // Create a pending intent to start the intent resolved here.
460 final IIntentSender failureTarget = mService.getIntentSenderLocked(
461 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
462 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
463 new String[]{ resolvedType },
464 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
465 | PendingIntent.FLAG_IMMUTABLE, null);
467 // Create a pending intent to start the ephemeral application; force it to be
468 // directed to the ephemeral package.
469 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
470 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
471 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
472 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
473 new String[]{ resolvedType },
474 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
475 | PendingIntent.FLAG_IMMUTABLE, null);
477 int flags = intent.getFlags();
478 intent = new Intent();
479 intent.setFlags(flags
480 | Intent.FLAG_ACTIVITY_NEW_TASK
481 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
482 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
483 rInfo.ephemeralResolveInfo.getPackageName());
484 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
485 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
488 callingUid = realCallingUid;
489 callingPid = realCallingPid;
491 rInfo = rInfo.ephemeralInstaller;
492 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
495 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
496 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
497 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
498 options, sourceRecord);
499 if (outActivity != null) {
503 if (r.appTimeTracker == null && sourceRecord != null) {
504 // If the caller didn't specify an explicit time tracker, we want to continue
505 // tracking under any it has.
506 r.appTimeTracker = sourceRecord.appTimeTracker;
509 final ActivityStack stack = mSupervisor.mFocusedStack;
510 if (voiceSession == null && (stack.mResumedActivity == null
511 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
512 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
513 realCallingPid, realCallingUid, "Activity start")) {
514 PendingActivityLaunch pal = new PendingActivityLaunch(r,
515 sourceRecord, startFlags, stack, callerApp);
516 mPendingActivityLaunches.add(pal);
517 ActivityOptions.abort(options);
518 return ActivityManager.START_SWITCHES_CANCELED;
522 if (mService.mDidAppSwitch) {
523 // This is the second allowed switch since we stopped switches,
524 // so now just generally allow switches. Use case: user presses
525 // home (switches disabled, switch to home, mDidAppSwitch now true);
526 // user taps a home icon (coming from home so allowed, we hit here
527 // and now allow anyone to switch again).
528 mService.mAppSwitchesAllowedTime = 0;
530 mService.mDidAppSwitch = true;
533 doPendingActivityLaunchesLocked(false);
536 mService.mWindowManager.deferSurfaceLayout();
537 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
538 true, options, inTask);
540 mService.mWindowManager.continueSurfaceLayout();
542 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
546 void postStartActivityUncheckedProcessing(
547 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
548 ActivityStack targetStack) {
550 if (result < START_SUCCESS) {
551 // If someone asked to have the keyguard dismissed on the next activity start,
552 // but we are not actually doing an activity switch... just dismiss the keyguard now,
553 // because we probably want to see whatever is behind it.
554 mSupervisor.notifyActivityDrawnForKeyguard();
558 // We're waiting for an activity launch to finish, but that activity simply
559 // brought another activity to front. Let startActivityMayWait() know about
560 // this, so it waits for the new activity to become visible instead.
561 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
562 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
565 int startedActivityStackId = INVALID_STACK_ID;
566 if (r.task != null && r.task.stack != null) {
567 startedActivityStackId = r.task.stack.mStackId;
568 } else if (mTargetStack != null) {
569 startedActivityStackId = targetStack.mStackId;
572 // If we launched the activity from a no display activity that was launched from the home
573 // screen, we also need to start recents to un-minimize the docked stack, since the
574 // noDisplay activity will be finished shortly after.
575 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
576 // visibility instead of using this flag.
577 final boolean noDisplayActivityOverHome = sourceRecord != null
578 && sourceRecord.noDisplay
579 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
580 if (startedActivityStackId == DOCKED_STACK_ID
581 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
582 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
583 final ActivityRecord topActivityHomeStack = homeStack != null
584 ? homeStack.topRunningActivityLocked() : null;
585 if (topActivityHomeStack == null
586 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
587 // We launch an activity while being in home stack, which means either launcher or
588 // recents into docked stack. We don't want the launched activity to be alone in a
589 // docked stack, so we want to immediately launch recents too.
590 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
591 mWindowManager.showRecentApps(true /* fromHome */);
596 if (startedActivityStackId == PINNED_STACK_ID
597 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
598 // The activity was already running in the pinned stack so it wasn't started, but either
599 // brought to the front or the new intent was delivered to it since it was already in
600 // front. Notify anyone interested in this piece of information.
601 mService.notifyPinnedActivityRestartAttemptLocked();
606 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
607 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
608 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
609 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
610 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
611 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
612 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
613 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
614 null /*container*/, null /*inTask*/);
615 if (mSupervisor.inResumeTopActivity) {
616 // If we are in resume section already, home activity will be initialized, but not
617 // resumed (to avoid recursive resume) and will stay that way until something pokes it
618 // again. We need to schedule another resume.
619 mSupervisor.scheduleResumeTopActivities();
623 void showConfirmDeviceCredential(int userId) {
624 // First, retrieve the stack that we want to resume after credential is confirmed.
625 ActivityStack targetStack;
626 ActivityStack fullscreenStack =
627 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
628 ActivityStack freeformStack =
629 mSupervisor.getStack(FREEFORM_WORKSPACE_STACK_ID);
630 if (fullscreenStack != null &&
631 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
632 // Single window case and the case that the docked stack is shown with fullscreen stack.
633 targetStack = fullscreenStack;
634 } else if (freeformStack != null &&
635 freeformStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
636 targetStack = freeformStack;
638 // The case that the docked stack is shown with recent.
639 targetStack = mSupervisor.getStack(HOME_STACK_ID);
641 if (targetStack == null) {
644 final KeyguardManager km = (KeyguardManager) mService.mContext
645 .getSystemService(Context.KEYGUARD_SERVICE);
646 final Intent credential =
647 km.createConfirmDeviceCredentialIntent(null, null, userId);
648 // For safety, check null here in case users changed the setting after the checking.
649 if (credential == null) {
652 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
653 if (activityRecord != null) {
654 final IIntentSender target = mService.getIntentSenderLocked(
655 ActivityManager.INTENT_SENDER_ACTIVITY,
656 activityRecord.launchedFromPackage,
657 activityRecord.launchedFromUid,
658 activityRecord.userId,
660 new Intent[] { activityRecord.intent },
661 new String[] { activityRecord.resolvedType },
662 PendingIntent.FLAG_CANCEL_CURRENT |
663 PendingIntent.FLAG_ONE_SHOT |
664 PendingIntent.FLAG_IMMUTABLE,
666 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
667 // Show confirm credentials activity.
668 startConfirmCredentialIntent(credential);
672 void startConfirmCredentialIntent(Intent intent) {
673 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
674 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
675 FLAG_ACTIVITY_TASK_ON_HOME);
676 final ActivityOptions options = ActivityOptions.makeBasic();
677 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
678 mService.mContext.startActivityAsUser(intent, options.toBundle(),
682 final int startActivityMayWait(IApplicationThread caller, int callingUid,
683 String callingPackage, Intent intent, String resolvedType,
684 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
685 IBinder resultTo, String resultWho, int requestCode, int startFlags,
686 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
687 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
688 IActivityContainer iContainer, TaskRecord inTask) {
689 // Refuse possible leaked file descriptors
690 if (intent != null && intent.hasFileDescriptors()) {
691 throw new IllegalArgumentException("File descriptors passed in Intent");
693 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
694 boolean componentSpecified = intent.getComponent() != null;
696 // Save a copy in case ephemeral needs it
697 final Intent ephemeralIntent = new Intent(intent);
698 // Don't modify the client's object!
699 intent = new Intent(intent);
701 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
703 UserInfo userInfo = mSupervisor.getUserInfo(userId);
704 if (userInfo != null && userInfo.isManagedProfile()) {
705 // Special case for managed profiles, if attempting to launch non-cryto aware
706 // app in a locked managed profile from an unlocked parent allow it to resolve
707 // as user will be sent via confirm credentials to unlock the profile.
708 UserManager userManager = UserManager.get(mService.mContext);
709 boolean profileLockedAndParentUnlockingOrUnlocked = false;
710 long token = Binder.clearCallingIdentity();
712 UserInfo parent = userManager.getProfileParent(userId);
713 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
714 && userManager.isUserUnlockingOrUnlocked(parent.id)
715 && !userManager.isUserUnlockingOrUnlocked(userId);
717 Binder.restoreCallingIdentity(token);
719 if (profileLockedAndParentUnlockingOrUnlocked) {
720 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
721 PackageManager.MATCH_DIRECT_BOOT_AWARE
722 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
726 // Collect information about the target of the Intent.
727 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
729 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
730 ActivityStackSupervisor.ActivityContainer container =
731 (ActivityStackSupervisor.ActivityContainer)iContainer;
732 synchronized (mService) {
733 if (container != null && container.mParentActivity != null &&
734 container.mParentActivity.state != RESUMED) {
735 // Cannot start a child activity if the parent is not resumed.
736 return ActivityManager.START_CANCELED;
738 final int realCallingPid = Binder.getCallingPid();
739 final int realCallingUid = Binder.getCallingUid();
741 if (callingUid >= 0) {
743 } else if (caller == null) {
744 callingPid = realCallingPid;
745 callingUid = realCallingUid;
747 callingPid = callingUid = -1;
750 final ActivityStack stack;
751 if (container == null || container.mStack.isOnHomeDisplay()) {
752 stack = mSupervisor.mFocusedStack;
754 stack = container.mStack;
756 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
757 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
758 "Starting activity when config will change = " + stack.mConfigWillChange);
760 final long origId = Binder.clearCallingIdentity();
763 (aInfo.applicationInfo.privateFlags
764 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
765 // This may be a heavy-weight process! Check to see if we already
766 // have another, different heavy-weight process running.
767 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
768 final ProcessRecord heavy = mService.mHeavyWeightProcess;
769 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
770 || !heavy.processName.equals(aInfo.processName))) {
771 int appCallingUid = callingUid;
772 if (caller != null) {
773 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
774 if (callerApp != null) {
775 appCallingUid = callerApp.info.uid;
777 Slog.w(TAG, "Unable to find app for caller " + caller
778 + " (pid=" + callingPid + ") when starting: "
779 + intent.toString());
780 ActivityOptions.abort(options);
781 return ActivityManager.START_PERMISSION_DENIED;
785 IIntentSender target = mService.getIntentSenderLocked(
786 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
787 appCallingUid, userId, null, null, 0, new Intent[] { intent },
788 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
789 | PendingIntent.FLAG_ONE_SHOT, null);
791 Intent newIntent = new Intent();
792 if (requestCode >= 0) {
793 // Caller is requesting a result.
794 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
796 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
797 new IntentSender(target));
798 if (heavy.activities.size() > 0) {
799 ActivityRecord hist = heavy.activities.get(0);
800 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
802 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
805 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
807 newIntent.setFlags(intent.getFlags());
808 newIntent.setClassName("android",
809 HeavyWeightSwitcherActivity.class.getName());
813 callingUid = Binder.getCallingUid();
814 callingPid = Binder.getCallingPid();
815 componentSpecified = true;
816 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
817 aInfo = rInfo != null ? rInfo.activityInfo : null;
819 aInfo = mService.getActivityInfoForUser(aInfo, userId);
825 final ActivityRecord[] outRecord = new ActivityRecord[1];
826 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
827 aInfo, rInfo, voiceSession, voiceInteractor,
828 resultTo, resultWho, requestCode, callingPid,
829 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
830 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
833 Binder.restoreCallingIdentity(origId);
835 if (stack.mConfigWillChange) {
836 // If the caller also wants to switch to a new configuration,
837 // do so now. This allows a clean switch, as we are waiting
838 // for the current activity to pause (so we will not destroy
839 // it), and have not yet started the next activity.
840 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
841 "updateConfiguration()");
842 stack.mConfigWillChange = false;
843 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
844 "Updating to new configuration after starting activity.");
845 mService.updateConfigurationLocked(config, null, false);
848 if (outResult != null) {
849 outResult.result = res;
850 if (res == ActivityManager.START_SUCCESS) {
851 mSupervisor.mWaitingActivityLaunched.add(outResult);
855 } catch (InterruptedException e) {
857 } while (outResult.result != START_TASK_TO_FRONT
858 && !outResult.timeout && outResult.who == null);
859 if (outResult.result == START_TASK_TO_FRONT) {
860 res = START_TASK_TO_FRONT;
863 if (res == START_TASK_TO_FRONT) {
864 ActivityRecord r = stack.topRunningActivityLocked();
865 if (r.nowVisible && r.state == RESUMED) {
866 outResult.timeout = false;
867 outResult.who = new ComponentName(r.info.packageName, r.info.name);
868 outResult.totalTime = 0;
869 outResult.thisTime = 0;
871 outResult.thisTime = SystemClock.uptimeMillis();
872 mSupervisor.mWaitingActivityVisible.add(outResult);
876 } catch (InterruptedException e) {
878 } while (!outResult.timeout && outResult.who == null);
883 final ActivityRecord launchedActivity = mReusedActivity != null
884 ? mReusedActivity : outRecord[0];
885 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
890 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
891 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
892 Bundle bOptions, int userId) {
893 if (intents == null) {
894 throw new NullPointerException("intents is null");
896 if (resolvedTypes == null) {
897 throw new NullPointerException("resolvedTypes is null");
899 if (intents.length != resolvedTypes.length) {
900 throw new IllegalArgumentException("intents are length different than resolvedTypes");
903 final int realCallingPid = Binder.getCallingPid();
904 final int realCallingUid = Binder.getCallingUid();
907 if (callingUid >= 0) {
909 } else if (caller == null) {
910 callingPid = realCallingPid;
911 callingUid = realCallingUid;
913 callingPid = callingUid = -1;
915 final long origId = Binder.clearCallingIdentity();
917 synchronized (mService) {
918 ActivityRecord[] outActivity = new ActivityRecord[1];
919 for (int i=0; i<intents.length; i++) {
920 Intent intent = intents[i];
921 if (intent == null) {
925 // Refuse possible leaked file descriptors
926 if (intent != null && intent.hasFileDescriptors()) {
927 throw new IllegalArgumentException("File descriptors passed in Intent");
930 boolean componentSpecified = intent.getComponent() != null;
932 // Don't modify the client's object!
933 intent = new Intent(intent);
935 // Collect information about the target of the Intent.
936 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
938 // TODO: New, check if this is correct
939 aInfo = mService.getActivityInfoForUser(aInfo, userId);
942 (aInfo.applicationInfo.privateFlags
943 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
944 throw new IllegalArgumentException(
945 "FLAG_CANT_SAVE_STATE not supported here");
948 ActivityOptions options = ActivityOptions.fromBundle(
949 i == intents.length - 1 ? bOptions : null);
950 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
951 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
952 callingPid, callingUid, callingPackage,
953 realCallingPid, realCallingUid, 0,
954 options, false, componentSpecified, outActivity, null, null);
959 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
963 Binder.restoreCallingIdentity(origId);
966 return START_SUCCESS;
969 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
970 // Trigger launch power hint if activity being launched is not in the current task
971 final ActivityStack focusStack = mSupervisor.getFocusedStack();
972 final ActivityRecord curTop = (focusStack == null)
973 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
974 if ((forceSend || (!mPowerHintSent && curTop != null &&
975 curTop.task != null && mStartActivity != null &&
976 curTop.task != mStartActivity.task )) &&
977 mService.mLocalPowerManager != null) {
978 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
979 mPowerHintSent = true;
983 void sendPowerHintForLaunchEndIfNeeded() {
984 // Trigger launch power hint if activity is launched
985 if (mPowerHintSent && mService.mLocalPowerManager != null) {
986 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
987 mPowerHintSent = false;
991 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
992 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
993 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
995 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
998 computeLaunchingTaskFlags();
1000 computeSourceStack();
1002 mIntent.setFlags(mLaunchFlags);
1004 mReusedActivity = getReusableIntentActivity();
1006 final int preferredLaunchStackId =
1007 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1009 if (mReusedActivity != null) {
1010 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1011 // still needs to be a lock task mode violation since the task gets cleared out and
1012 // the device would otherwise leave the locked task.
1013 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
1014 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1015 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1016 mSupervisor.showLockTaskToast();
1017 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1018 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1021 if (mStartActivity.task == null) {
1022 mStartActivity.task = mReusedActivity.task;
1024 if (mReusedActivity.task.intent == null) {
1025 // This task was started because of movement of the activity based on affinity...
1026 // Now that we are actually launching it, we can assign the base intent.
1027 mReusedActivity.task.setIntent(mStartActivity);
1030 // This code path leads to delivering a new intent, we want to make sure we schedule it
1031 // as the first operation, in case the activity will be resumed as a result of later
1033 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1034 || mLaunchSingleInstance || mLaunchSingleTask) {
1035 // In this situation we want to remove all activities from the task up to the one
1036 // being started. In most cases this means we are resetting the task to its initial
1038 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
1039 mStartActivity, mLaunchFlags);
1041 if (top.frontOfTask) {
1042 // Activity aliases may mean we use different intents for the top activity,
1043 // so make sure the task now has the identity of the new intent.
1044 top.task.setIntent(mStartActivity);
1046 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1047 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1048 mStartActivity.launchedFromPackage);
1052 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1054 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
1056 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1057 // We don't need to start a new activity, and the client said not to do anything
1058 // if that is the case, so this is it! And for paranoia, make sure we have
1059 // correctly resumed the top activity.
1060 resumeTargetStackIfNeeded();
1061 return START_RETURN_INTENT_TO_CALLER;
1063 setTaskFromIntentActivity(mReusedActivity);
1065 if (!mAddingToTask && mReuseTask == null) {
1066 // We didn't do anything... but it was needed (a.k.a., client don't use that
1067 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1068 resumeTargetStackIfNeeded();
1069 return START_TASK_TO_FRONT;
1073 if (mStartActivity.packageName == null) {
1074 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1075 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1076 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1077 mStartActivity.requestCode, RESULT_CANCELED, null);
1079 ActivityOptions.abort(mOptions);
1080 return START_CLASS_NOT_FOUND;
1083 // If the activity being launched is the same as the one currently at the top, then
1084 // we need to check if it should only be launched once.
1085 final ActivityStack topStack = mSupervisor.mFocusedStack;
1086 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1087 final boolean dontStart = top != null && mStartActivity.resultTo == null
1088 && top.realActivity.equals(mStartActivity.realActivity)
1089 && top.userId == mStartActivity.userId
1090 && top.app != null && top.app.thread != null
1091 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1092 || mLaunchSingleTop || mLaunchSingleTask);
1094 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1095 // For paranoia, make sure we have correctly resumed the top activity.
1096 topStack.mLastPausedActivity = null;
1098 mSupervisor.resumeFocusedStackTopActivityLocked();
1100 ActivityOptions.abort(mOptions);
1101 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1102 // We don't need to start a new activity, and the client said not to do
1103 // anything if that is the case, so this is it!
1104 return START_RETURN_INTENT_TO_CALLER;
1106 top.deliverNewIntentLocked(
1107 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1109 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1110 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1111 mSupervisor.handleNonResizableTaskIfNeeded(
1112 top.task, preferredLaunchStackId, topStack.mStackId);
1114 return START_DELIVERED_TO_TOP;
1117 boolean newTask = false;
1118 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1119 ? mSourceRecord.task : null;
1121 // Should this be considered a new task?
1122 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1123 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1125 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1127 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1128 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1129 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1131 if (!mMovedOtherTask) {
1132 // If stack id is specified in activity options, usually it means that activity is
1133 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1134 // that case we check the target stack.
1135 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1136 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1138 } else if (mSourceRecord != null) {
1139 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1140 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1141 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1144 final int result = setTaskFromSourceRecord();
1145 if (result != START_SUCCESS) {
1148 } else if (mInTask != null) {
1149 // The caller is asking that the new activity be started in an explicit
1150 // task it has provided to us.
1151 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1152 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1153 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1156 final int result = setTaskFromInTask();
1157 if (result != START_SUCCESS) {
1161 // This not being started from an existing activity, and not part of a new task...
1162 // just put it in the top task, though these days this case should never happen.
1163 setTaskToCurrentTopOrCreateNewTask();
1166 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1167 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1169 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1170 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1173 EventLog.writeEvent(
1174 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1176 ActivityStack.logStartActivity(
1177 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1178 mTargetStack.mLastPausedActivity = null;
1180 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1182 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1184 if (!mLaunchTaskBehind) {
1185 // TODO(b/26381750): Remove this code after verification that all the decision
1186 // points above moved targetStack to the front which will also set the focus
1188 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1190 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1191 if (!mTargetStack.isFocusable()
1192 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1193 && mStartActivity != topTaskActivity)) {
1194 // If the activity is not focusable, we can't resume it, but still would like to
1195 // make sure it becomes visible as it starts (this will also trigger entry
1196 // animation). An example of this are PIP activities.
1197 // Also, we don't want to resume activities in a task that currently has an overlay
1198 // as the starting activity just needs to be in the visible paused state until the
1200 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1201 // Go ahead and tell window manager to execute app transition for this activity
1202 // since the app transition will not be triggered through the resume channel.
1203 mWindowManager.executeAppTransition();
1205 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1209 mTargetStack.addRecentActivityLocked(mStartActivity);
1211 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1213 mSupervisor.handleNonResizableTaskIfNeeded(
1214 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
1216 return START_SUCCESS;
1219 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1220 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1221 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1227 mCallingUid = r.launchedFromUid;
1228 mSourceRecord = sourceRecord;
1229 mVoiceSession = voiceSession;
1230 mVoiceInteractor = voiceInteractor;
1232 mLaunchBounds = getOverrideBounds(r, options, inTask);
1234 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1235 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1236 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1237 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1238 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1239 mLaunchTaskBehind = r.mLaunchTaskBehind
1240 && !mLaunchSingleTask && !mLaunchSingleInstance
1241 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1243 sendNewTaskResultRequestIfNeeded();
1245 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1246 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1249 // If we are actually going to launch in to a new task, there are some cases where
1250 // we further want to do multiple task.
1251 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1252 if (mLaunchTaskBehind
1253 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1254 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1258 // We'll invoke onUserLeaving before onPause only if the launching
1259 // activity did not explicitly state that this is an automated launch.
1260 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1261 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1262 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1264 // If the caller has asked not to resume at this point, we make note
1265 // of this in the record so that we can skip it when trying to find
1266 // the top running activity.
1267 mDoResume = doResume;
1268 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1269 r.delayedResume = true;
1273 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1274 r.mTaskOverlay = true;
1275 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1276 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1277 if (top != null && !top.visible) {
1279 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1282 mAvoidMoveToFront = true;
1286 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1289 // In some flows in to this function, we retrieve the task record and hold on to it
1290 // without a lock before calling back in to here... so the task at this point may
1291 // not actually be in recents. Check for that, and if it isn't in recents just
1292 // consider it invalid.
1293 if (inTask != null && !inTask.inRecents) {
1294 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1298 mStartFlags = startFlags;
1299 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1300 // is the same as the one making the call... or, as a special case, if we do not know
1301 // the caller then we count the current top activity as the caller.
1302 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1303 ActivityRecord checkedCaller = sourceRecord;
1304 if (checkedCaller == null) {
1305 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1308 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1309 // Caller is not the same as launcher, so always needed.
1310 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1314 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1317 private void sendNewTaskResultRequestIfNeeded() {
1318 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1319 && mStartActivity.resultTo.task.stack != null) {
1320 // For whatever reason this activity is being launched into a new task...
1321 // yet the caller has requested a result back. Well, that is pretty messed up,
1322 // so instead immediately send back a cancel and let the new task continue launched
1323 // as normal without a dependency on its originator.
1324 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1325 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1326 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1327 mStartActivity.resultTo = null;
1331 private void computeLaunchingTaskFlags() {
1332 // If the caller is not coming from another activity, but has given us an explicit task into
1333 // which they would like us to launch the new activity, then let's see about doing that.
1334 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1335 final Intent baseIntent = mInTask.getBaseIntent();
1336 final ActivityRecord root = mInTask.getRootActivity();
1337 if (baseIntent == null) {
1338 ActivityOptions.abort(mOptions);
1339 throw new IllegalArgumentException("Launching into task without base intent: "
1343 // If this task is empty, then we are adding the first activity -- it
1344 // determines the root, and must be launching as a NEW_TASK.
1345 if (mLaunchSingleInstance || mLaunchSingleTask) {
1346 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1347 ActivityOptions.abort(mOptions);
1348 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1349 + mStartActivity + " into different task " + mInTask);
1352 ActivityOptions.abort(mOptions);
1353 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1354 + " has root " + root + " but target is singleInstance/Task");
1358 // If task is empty, then adopt the interesting intent launch flags in to the
1359 // activity being started.
1361 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1362 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1363 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1364 | (baseIntent.getFlags() & flagsOfInterest);
1365 mIntent.setFlags(mLaunchFlags);
1366 mInTask.setIntent(mStartActivity);
1367 mAddingToTask = true;
1369 // If the task is not empty and the caller is asking to start it as the root of
1370 // a new task, then we don't actually want to start this on the task. We will
1371 // bring the task to the front, and possibly give it a new intent.
1372 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1373 mAddingToTask = false;
1376 mAddingToTask = true;
1379 mReuseTask = mInTask;
1382 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1383 // when in freeform workspace.
1384 // Also put noDisplay activities in the source task. These by itself can be placed
1385 // in any task/stack, however it could launch other activities like ResolverActivity,
1386 // and we want those to stay in the original task.
1387 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1388 && mSourceRecord.isFreeform()) {
1389 mAddingToTask = true;
1393 if (mInTask == null) {
1394 if (mSourceRecord == null) {
1395 // This activity is not being started from another... in this
1396 // case we -always- start a new task.
1397 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1398 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1399 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1400 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1402 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1403 // The original activity who is starting us is running as a single
1404 // instance... this new activity it is starting must go on its
1406 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1407 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1408 // The activity being started is a single instance... it always
1409 // gets launched into its own task.
1410 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1415 private void computeSourceStack() {
1416 if (mSourceRecord == null) {
1417 mSourceStack = null;
1420 if (!mSourceRecord.finishing) {
1421 mSourceStack = mSourceRecord.task.stack;
1425 // If the source is finishing, we can't further count it as our source. This is because the
1426 // task it is associated with may now be empty and on its way out, so we don't want to
1427 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1428 // a task for it. But save the task information so it can be used when creating the new task.
1429 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1430 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1431 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1432 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1433 mNewTaskInfo = mSourceRecord.info;
1434 mNewTaskIntent = mSourceRecord.task.intent;
1436 mSourceRecord = null;
1437 mSourceStack = null;
1441 * Decide whether the new activity should be inserted into an existing task. Returns null
1442 * if not or an ActivityRecord with the task into which the new activity should be added.
1444 private ActivityRecord getReusableIntentActivity() {
1445 // We may want to try to place the new activity in to an existing task. We always
1446 // do this if the target activity is singleTask or singleInstance; we will also do
1447 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1448 // us to still place it in a new task: multi task, always doc mode, or being asked to
1449 // launch this as a new task behind the current one.
1450 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1451 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1452 || mLaunchSingleInstance || mLaunchSingleTask;
1453 // If bring to front is requested, and no result is requested and we have not been given
1454 // an explicit task to launch in to, and we can find a task that was started with this
1455 // same component, then instead of launching bring that one to the front.
1456 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1457 ActivityRecord intentActivity = null;
1458 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1459 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1460 intentActivity = task != null ? task.getTopActivity() : null;
1461 } else if (putIntoExistingTask) {
1462 if (mLaunchSingleInstance) {
1463 // There can be one and only one instance of single instance activity in the
1464 // history, and it is always in its own unique task, so we do a special search.
1465 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
1466 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1467 // For the launch adjacent case we only want to put the activity in an existing
1468 // task if the activity already exists in the history.
1469 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1470 !mLaunchSingleTask);
1472 // Otherwise find the best task to put the activity in.
1473 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1476 return intentActivity;
1479 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1480 mTargetStack = intentActivity.task.stack;
1481 mTargetStack.mLastPausedActivity = null;
1482 // If the target task is not in the front, then we need to bring it to the front...
1483 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1484 // the same behavior as if a new instance was being started, which means not bringing it
1485 // to the front if the caller is not itself in the front.
1486 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1487 ActivityRecord curTop = (focusStack == null)
1488 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1491 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1492 && !mAvoidMoveToFront) {
1493 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1494 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1495 mSourceStack.topActivity().task == mSourceRecord.task)) {
1496 // We really do want to push this one into the user's face, right now.
1497 if (mLaunchTaskBehind && mSourceRecord != null) {
1498 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1500 mMovedOtherTask = true;
1502 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1503 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1504 // So no point resuming any of the activities here, it just wastes one extra
1505 // resuming, plus enter AND exit transitions.
1506 // Here we only want to bring the target stack forward. Transition will be applied
1507 // to the new activity that's started after the old ones are gone.
1508 final boolean willClearTask =
1509 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1510 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1511 if (!willClearTask) {
1512 final ActivityStack launchStack = getLaunchStack(
1513 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
1514 if (launchStack == null || launchStack == mTargetStack) {
1515 // We only want to move to the front, if we aren't going to launch on a
1516 // different stack. If we launch on a different stack, we will put the
1517 // task on top there.
1518 mTargetStack.moveTaskToFrontLocked(
1519 intentActivity.task, mNoAnimation, mOptions,
1520 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1521 mMovedToFront = true;
1522 } else if (launchStack.mStackId == DOCKED_STACK_ID
1523 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1524 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1525 // If we want to launch adjacent and mTargetStack is not the computed
1526 // launch stack - move task to top of computed stack.
1527 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1528 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1531 // TODO: This should be reevaluated in MW v2.
1532 // We choose to move task to front instead of launching it adjacent
1533 // when specific stack was requested explicitly and it appeared to be
1534 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1535 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1536 mOptions, mStartActivity.appTimeTracker,
1537 "bringToFrontInsteadOfAdjacentLaunch");
1539 mMovedToFront = true;
1543 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
1546 if (!mMovedToFront && mDoResume) {
1547 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1548 + " from " + intentActivity);
1549 mTargetStack.moveToFront("intentActivityFound");
1552 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1553 mTargetStack.mStackId);
1555 // If the caller has requested that the target task be reset, then do so.
1556 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1557 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1559 return intentActivity;
1562 private void updateTaskReturnToType(
1563 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1564 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1565 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1566 // Caller wants to appear on home activity.
1567 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1569 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1570 // Task will be launched over the home stack, so return home.
1571 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1575 // Else we are coming from an application stack so return to an application.
1576 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1579 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1580 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1581 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1582 // The caller has requested to completely replace any existing task with its new
1583 // activity. Well that should not be too hard...
1584 mReuseTask = intentActivity.task;
1585 mReuseTask.performClearTaskLocked();
1586 mReuseTask.setIntent(mStartActivity);
1587 // When we clear the task - focus will be adjusted, which will bring another task
1588 // to top before we launch the activity we need. This will temporary swap their
1589 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1590 mMovedOtherTask = true;
1591 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1592 || mLaunchSingleInstance || mLaunchSingleTask) {
1593 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1596 // A special case: we need to start the activity because it is not currently
1597 // running, and the caller has asked to clear the current task to have this
1598 // activity at the top.
1599 mAddingToTask = true;
1600 // Now pretend like this activity is being started by the top of its task, so it
1601 // is put in the right place.
1602 mSourceRecord = intentActivity;
1603 final TaskRecord task = mSourceRecord.task;
1604 if (task != null && task.stack == null) {
1605 // Target stack got cleared when we all activities were removed above.
1606 // Go ahead and reset it.
1607 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1608 null /* bounds */, mLaunchFlags, mOptions);
1609 mTargetStack.addTask(task,
1610 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1613 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1614 // In this case the top activity on the task is the same as the one being launched,
1615 // so we take that as a request to bring the task to the foreground. If the top
1616 // activity in the task is the root activity, deliver this new intent to it if it
1618 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1619 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1620 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1621 intentActivity.task);
1622 if (intentActivity.frontOfTask) {
1623 intentActivity.task.setIntent(mStartActivity);
1625 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1626 mStartActivity.launchedFromPackage);
1627 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
1628 // In this case we are launching the root activity of the task, but with a
1629 // different intent. We should start a new instance on top.
1630 mAddingToTask = true;
1631 mSourceRecord = intentActivity;
1633 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1634 // In this case an activity is being launched in to an existing task, without
1635 // resetting that task. This is typically the situation of launching an activity
1636 // from a notification or shortcut. We want to place the new activity on top of the
1638 mAddingToTask = true;
1639 mSourceRecord = intentActivity;
1640 } else if (!intentActivity.task.rootWasReset) {
1641 // In this case we are launching into an existing task that has not yet been started
1642 // from its front door. The current task has been brought to the front. Ideally,
1643 // we'd probably like to place this new task at the bottom of its stack, but that's
1644 // a little hard to do with the current organization of the code so for now we'll
1646 intentActivity.task.setIntent(mStartActivity);
1650 private void resumeTargetStackIfNeeded() {
1652 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1653 if (!mMovedToFront) {
1654 // Make sure to notify Keyguard as well if we are not running an app transition
1656 mSupervisor.notifyActivityDrawnForKeyguard();
1659 ActivityOptions.abort(mOptions);
1661 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1664 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1665 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1668 if (mReuseTask == null) {
1669 final TaskRecord task = mTargetStack.createTaskRecord(
1670 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1671 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1672 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1673 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1674 mStartActivity.setTask(task, taskToAffiliate);
1675 if (mLaunchBounds != null) {
1676 final int stackId = mTargetStack.mStackId;
1677 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1678 mService.resizeStack(
1679 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1681 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1684 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1685 "Starting new activity " +
1686 mStartActivity + " in new task " + mStartActivity.task);
1688 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1692 private int setTaskFromSourceRecord() {
1693 final TaskRecord sourceTask = mSourceRecord.task;
1694 // We only want to allow changing stack if the target task is not the top one,
1695 // otherwise we would move the launching task to the other side, rather than show
1696 // two side by side.
1697 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1698 if (moveStackAllowed) {
1699 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1703 if (mTargetStack == null) {
1704 mTargetStack = sourceTask.stack;
1705 } else if (mTargetStack != sourceTask.stack) {
1706 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1707 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1710 mTargetStack.moveToFront("sourceStackToFront");
1712 final TaskRecord topTask = mTargetStack.topTask();
1713 if (topTask != sourceTask && !mAvoidMoveToFront) {
1714 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1715 mStartActivity.appTimeTracker, "sourceTaskToFront");
1717 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1718 // In this case, we are adding the activity to an existing task, but the caller has
1719 // asked to clear that task if the activity is already running.
1720 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1721 mKeepCurTransition = true;
1723 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1724 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1725 // For paranoia, make sure we have correctly resumed the top activity.
1726 mTargetStack.mLastPausedActivity = null;
1728 mSupervisor.resumeFocusedStackTopActivityLocked();
1730 ActivityOptions.abort(mOptions);
1731 return START_DELIVERED_TO_TOP;
1733 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1734 // In this case, we are launching an activity in our own task that may already be
1735 // running somewhere in the history, and we want to shuffle it to the front of the
1737 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1739 final TaskRecord task = top.task;
1740 task.moveActivityToFrontLocked(top);
1741 top.updateOptionsLocked(mOptions);
1742 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1743 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1744 mTargetStack.mLastPausedActivity = null;
1746 mSupervisor.resumeFocusedStackTopActivityLocked();
1748 return START_DELIVERED_TO_TOP;
1752 // An existing activity is starting this new activity, so we want to keep the new one in
1753 // the same task as the one that is starting it.
1754 mStartActivity.setTask(sourceTask, null);
1755 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1756 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1757 return START_SUCCESS;
1760 private int setTaskFromInTask() {
1761 if (mLaunchBounds != null) {
1762 mInTask.updateOverrideConfiguration(mLaunchBounds);
1763 int stackId = mInTask.getLaunchStackId();
1764 if (stackId != mInTask.stack.mStackId) {
1765 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
1766 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1767 stackId = stack.mStackId;
1769 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1770 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1773 mTargetStack = mInTask.stack;
1774 mTargetStack.moveTaskToFrontLocked(
1775 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1777 // Check whether we should actually launch the new activity in to the task,
1778 // or just reuse the current activity on top.
1779 ActivityRecord top = mInTask.getTopActivity();
1780 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1781 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1782 || mLaunchSingleTop || mLaunchSingleTask) {
1783 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1784 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1785 // We don't need to start a new activity, and the client said not to do
1786 // anything if that is the case, so this is it!
1787 return START_RETURN_INTENT_TO_CALLER;
1789 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1790 return START_DELIVERED_TO_TOP;
1794 if (!mAddingToTask) {
1795 // We don't actually want to have this activity added to the task, so just
1796 // stop here but still tell the caller that we consumed the intent.
1797 ActivityOptions.abort(mOptions);
1798 return START_TASK_TO_FRONT;
1801 mStartActivity.setTask(mInTask, null);
1802 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1803 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1805 return START_SUCCESS;
1808 private void setTaskToCurrentTopOrCreateNewTask() {
1809 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1812 mTargetStack.moveToFront("addingToTopTask");
1814 final ActivityRecord prev = mTargetStack.topActivity();
1815 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1816 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1817 mStartActivity.info, mIntent, null, null, true);
1818 mStartActivity.setTask(task, null);
1819 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1820 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1821 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1824 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1825 boolean launchSingleTask, int launchFlags) {
1826 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1827 (launchSingleInstance || launchSingleTask)) {
1828 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1829 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1830 "\"singleInstance\" or \"singleTask\"");
1832 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1834 switch (r.info.documentLaunchMode) {
1835 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1837 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1838 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1840 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1841 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1843 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1844 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1851 final void doPendingActivityLaunchesLocked(boolean doResume) {
1852 while (!mPendingActivityLaunches.isEmpty()) {
1853 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1854 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
1856 final int result = startActivityUnchecked(
1857 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1858 postStartActivityUncheckedProcessing(
1859 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1861 } catch (Exception e) {
1862 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1863 pal.sendErrorResult(e.getMessage());
1868 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1869 int launchFlags, ActivityOptions aOptions) {
1870 final TaskRecord task = r.task;
1871 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1872 return mSupervisor.mHomeStack;
1875 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
1876 if (stack != null) {
1880 if (task != null && task.stack != null) {
1882 if (stack.isOnHomeDisplay()) {
1883 if (mSupervisor.mFocusedStack != stack) {
1884 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1885 "computeStackFocus: Setting " + "focused stack to r=" + r
1888 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1889 "computeStackFocus: Focused stack already="
1890 + mSupervisor.mFocusedStack);
1896 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1897 if (container != null) {
1898 // The first time put it on the desired stack, after this put on task stack.
1899 r.mInitialActivityContainer = null;
1900 return container.mStack;
1903 // The fullscreen stack can contain any task regardless of if the task is resizeable
1904 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1905 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1906 // we can also put it in the focused stack.
1907 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1908 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1909 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1910 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
1911 if (canUseFocusedStack && (!newTask
1912 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1913 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1914 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1915 return mSupervisor.mFocusedStack;
1918 // We first try to put the task in the first dynamic stack.
1919 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1920 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1921 stack = homeDisplayStacks.get(stackNdx);
1922 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1923 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1924 "computeStackFocus: Setting focused stack=" + stack);
1929 // If there is no suitable dynamic stack then we figure out which static stack to use.
1930 final int stackId = task != null ? task.getLaunchStackId() :
1931 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1932 FULLSCREEN_WORKSPACE_STACK_ID;
1933 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1934 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1935 + r + " stackId=" + stack.mStackId);
1939 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1940 ActivityOptions aOptions) {
1942 // We are reusing a task, keep the stack!
1943 if (mReuseTask != null) {
1944 return mReuseTask.stack;
1947 final int launchStackId =
1948 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1950 if (isValidLaunchStackId(launchStackId, r)) {
1951 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
1952 } else if (launchStackId == DOCKED_STACK_ID) {
1953 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1954 // for this activity, so we put the activity in the fullscreen stack.
1955 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1958 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
1961 // Otherwise handle adjacent launch.
1963 // The parent activity doesn't want to launch the activity on top of itself, but
1964 // instead tries to put it onto other side in side-by-side mode.
1965 final ActivityStack parentStack = task != null ? task.stack
1966 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1967 : mSupervisor.mFocusedStack;
1969 if (parentStack != mSupervisor.mFocusedStack) {
1970 // If task's parent stack is not focused - use it during adjacent launch.
1973 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1974 // If task is already on top of focused stack - use it. We don't want to move the
1975 // existing focused task to adjacent stack, just deliver new intent in this case.
1976 return mSupervisor.mFocusedStack;
1979 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1980 // If parent was in docked stack, the natural place to launch another activity
1981 // will be fullscreen, so it can appear alongside the docked window.
1982 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1985 // If the parent is not in the docked stack, we check if there is docked window
1986 // and if yes, we will launch into that stack. If not, we just put the new
1987 // activity into parent's stack, because we can't find a better place.
1988 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
1989 if (dockedStack != null
1990 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
1991 // There is a docked stack, but it isn't visible, so we can't launch into that.
2000 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2001 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2002 || !StackId.isStaticStack(stackId)) {
2006 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2007 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2011 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2015 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2019 final boolean supportsPip = mService.mSupportsPictureInPicture
2020 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2021 if (stackId == PINNED_STACK_ID && !supportsPip) {
2027 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2028 Rect newBounds = null;
2029 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2030 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2031 options, options.getLaunchStackId())) {
2032 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2038 void setWindowManager(WindowManagerService wm) {
2039 mWindowManager = wm;
2042 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2043 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2044 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2045 if (pal.stack == stack) {
2046 mPendingActivityLaunches.remove(palNdx);