2 * Copyright (C) 2016 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.server.am;
19 import static android.app.Activity.RESULT_CANCELED;
20 import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
21 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
22 import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
23 import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
24 import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
25 import static android.app.ActivityManager.START_SUCCESS;
26 import static android.app.ActivityManager.START_TASK_TO_FRONT;
27 import static android.app.ActivityManager.StackId;
28 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
29 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
30 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
31 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
32 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
33 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
34 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
35 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
36 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
37 import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
38 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
39 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
40 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
41 import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
42 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
43 import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
44 import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
45 import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
46 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
47 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
48 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
49 import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
50 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
51 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
52 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
53 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
54 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
55 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
56 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
57 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
58 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
59 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
60 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
61 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
62 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
63 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
64 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
65 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
66 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
67 import static com.android.server.am.ActivityManagerService.ANIMATE;
68 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
69 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
70 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
71 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
72 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
73 import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
74 import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
75 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
76 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
77 import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
78 import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
80 import android.app.ActivityManager;
81 import android.app.ActivityOptions;
82 import android.app.AppGlobals;
83 import android.app.IActivityContainer;
84 import android.app.IActivityManager;
85 import android.app.IApplicationThread;
86 import android.app.KeyguardManager;
87 import android.app.PendingIntent;
88 import android.app.ProfilerInfo;
89 import android.content.ComponentName;
90 import android.content.Context;
91 import android.content.IIntentSender;
92 import android.content.Intent;
93 import android.content.IntentSender;
94 import android.content.pm.ActivityInfo;
95 import android.content.pm.ApplicationInfo;
96 import android.content.pm.PackageManager;
97 import android.content.pm.ResolveInfo;
98 import android.content.pm.UserInfo;
99 import android.content.res.Configuration;
100 import android.graphics.Rect;
101 import android.os.Binder;
102 import android.os.Build;
103 import android.os.Bundle;
104 import android.os.IBinder;
105 import android.os.PowerManagerInternal;
106 import android.os.Process;
107 import android.os.RemoteException;
108 import android.os.SystemClock;
109 import android.os.UserHandle;
110 import android.os.UserManager;
111 import android.service.voice.IVoiceInteractionSession;
112 import android.util.EventLog;
113 import android.util.Slog;
114 import android.view.Display;
116 import com.android.internal.app.HeavyWeightSwitcherActivity;
117 import com.android.internal.app.IVoiceInteractor;
118 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
119 import com.android.server.wm.WindowManagerService;
121 import java.util.ArrayList;
124 * Controller for interpreting how and then launching activities.
126 * This class collects all the logic for determining how an intent and flags should be turned into
127 * an activity and associated task and stack.
129 class ActivityStarter {
130 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
131 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
132 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
133 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
134 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
136 // TODO b/30204367 remove when the platform fully supports ephemeral applications
137 private static final boolean USE_DEFAULT_EPHEMERAL_LAUNCHER = false;
139 private final ActivityManagerService mService;
140 private final ActivityStackSupervisor mSupervisor;
141 private ActivityStartInterceptor mInterceptor;
142 private WindowManagerService mWindowManager;
144 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
146 // Share state variable among methods when starting an activity.
147 private ActivityRecord mStartActivity;
148 private ActivityRecord mReusedActivity;
149 private Intent mIntent;
150 private int mCallingUid;
151 private ActivityOptions mOptions;
153 private boolean mLaunchSingleTop;
154 private boolean mLaunchSingleInstance;
155 private boolean mLaunchSingleTask;
156 private boolean mLaunchTaskBehind;
157 private int mLaunchFlags;
159 private Rect mLaunchBounds;
161 private ActivityRecord mNotTop;
162 private boolean mDoResume;
163 private int mStartFlags;
164 private ActivityRecord mSourceRecord;
166 private TaskRecord mInTask;
167 private boolean mAddingToTask;
168 private TaskRecord mReuseTask;
170 private ActivityInfo mNewTaskInfo;
171 private Intent mNewTaskIntent;
172 private ActivityStack mSourceStack;
173 private ActivityStack mTargetStack;
174 // Indicates that we moved other task and are going to put something on top soon, so
175 // we don't want to show it redundantly or accidentally change what's shown below.
176 private boolean mMovedOtherTask;
177 private boolean mMovedToFront;
178 private boolean mNoAnimation;
179 private boolean mKeepCurTransition;
180 private boolean mAvoidMoveToFront;
181 private boolean mPowerHintSent;
183 private IVoiceInteractionSession mVoiceSession;
184 private IVoiceInteractor mVoiceInteractor;
186 private void reset() {
187 mStartActivity = null;
192 mLaunchSingleTop = false;
193 mLaunchSingleInstance = false;
194 mLaunchSingleTask = false;
195 mLaunchTaskBehind = false;
198 mLaunchBounds = null;
203 mSourceRecord = null;
206 mAddingToTask = false;
210 mNewTaskIntent = null;
214 mMovedOtherTask = false;
215 mMovedToFront = false;
216 mNoAnimation = false;
217 mKeepCurTransition = false;
218 mAvoidMoveToFront = false;
220 mVoiceSession = null;
221 mVoiceInteractor = null;
224 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
226 mSupervisor = supervisor;
227 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
230 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
231 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
232 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
233 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
234 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
235 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
236 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
238 int err = ActivityManager.START_SUCCESS;
240 ProcessRecord callerApp = null;
241 if (caller != null) {
242 callerApp = mService.getRecordForAppLocked(caller);
243 if (callerApp != null) {
244 callingPid = callerApp.pid;
245 callingUid = callerApp.info.uid;
247 Slog.w(TAG, "Unable to find app for caller " + caller
248 + " (pid=" + callingPid + ") when starting: "
249 + intent.toString());
250 err = ActivityManager.START_PERMISSION_DENIED;
254 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
256 if (err == ActivityManager.START_SUCCESS) {
257 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
258 + "} from uid " + callingUid
259 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
260 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
261 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
262 container.mActivityDisplay.mDisplayId)));
265 ActivityRecord sourceRecord = null;
266 ActivityRecord resultRecord = null;
267 if (resultTo != null) {
268 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
269 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
270 "Will send result to " + resultTo + " " + sourceRecord);
271 if (sourceRecord != null) {
272 if (requestCode >= 0 && !sourceRecord.finishing) {
273 resultRecord = sourceRecord;
278 final int launchFlags = intent.getFlags();
280 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
281 // Transfer the result target from the source activity to the new
282 // one being started, including any failures.
283 if (requestCode >= 0) {
284 ActivityOptions.abort(options);
285 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
287 resultRecord = sourceRecord.resultTo;
288 if (resultRecord != null && !resultRecord.isInStackLocked()) {
291 resultWho = sourceRecord.resultWho;
292 requestCode = sourceRecord.requestCode;
293 sourceRecord.resultTo = null;
294 if (resultRecord != null) {
295 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
297 if (sourceRecord.launchedFromUid == callingUid) {
298 // The new activity is being launched from the same uid as the previous
299 // activity in the flow, and asking to forward its result back to the
300 // previous. In this case the activity is serving as a trampoline between
301 // the two, so we also want to update its launchedFromPackage to be the
302 // same as the previous activity. Note that this is safe, since we know
303 // these two packages come from the same uid; the caller could just as
304 // well have supplied that same package name itself. This specifially
305 // deals with the case of an intent picker/chooser being launched in the app
306 // flow to redirect to an activity picked by the user, where we want the final
307 // activity to consider it to have been launched by the previous app activity.
308 callingPackage = sourceRecord.launchedFromPackage;
312 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
313 // We couldn't find a class that can handle the given Intent.
314 // That's the end of that!
315 err = ActivityManager.START_INTENT_NOT_RESOLVED;
318 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
319 // We couldn't find the specific class specified in the Intent.
320 // Also the end of the line.
321 err = ActivityManager.START_CLASS_NOT_FOUND;
324 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
325 && sourceRecord.task.voiceSession != null) {
326 // If this activity is being launched as part of a voice session, we need
327 // to ensure that it is safe to do so. If the upcoming activity will also
328 // be part of the voice session, we can only launch it if it has explicitly
329 // said it supports the VOICE category, or it is a part of the calling app.
330 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
331 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
333 intent.addCategory(Intent.CATEGORY_VOICE);
334 if (!AppGlobals.getPackageManager().activitySupportsIntent(
335 intent.getComponent(), intent, resolvedType)) {
337 "Activity being started in current voice task does not support voice: "
339 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
341 } catch (RemoteException e) {
342 Slog.w(TAG, "Failure checking voice capabilities", e);
343 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
348 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
349 // If the caller is starting a new voice session, just make sure the target
350 // is actually allowing it to run this way.
352 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
353 intent, resolvedType)) {
355 "Activity being started in new voice task does not support: "
357 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
359 } catch (RemoteException e) {
360 Slog.w(TAG, "Failure checking voice capabilities", e);
361 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
365 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
367 if (err != START_SUCCESS) {
368 if (resultRecord != null) {
369 resultStack.sendActivityResultLocked(
370 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
372 ActivityOptions.abort(options);
376 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
377 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
378 resultRecord, resultStack, options);
379 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
380 callingPid, resolvedType, aInfo.applicationInfo);
382 if (mService.mController != null) {
384 // The Intent we give to the watcher has the extra data
385 // stripped off, since it can contain private information.
386 Intent watchIntent = intent.cloneFilter();
387 abort |= !mService.mController.activityStarting(watchIntent,
388 aInfo.applicationInfo.packageName);
389 } catch (RemoteException e) {
390 mService.mController = null;
394 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
395 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
397 intent = mInterceptor.mIntent;
398 rInfo = mInterceptor.mRInfo;
399 aInfo = mInterceptor.mAInfo;
400 resolvedType = mInterceptor.mResolvedType;
401 inTask = mInterceptor.mInTask;
402 callingPid = mInterceptor.mCallingPid;
403 callingUid = mInterceptor.mCallingUid;
404 options = mInterceptor.mActivityOptions;
406 if (resultRecord != null) {
407 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
408 RESULT_CANCELED, null);
410 // We pretend to the caller that it was really started, but
411 // they will just get a cancel result.
412 ActivityOptions.abort(options);
413 return START_SUCCESS;
416 // If permissions need a review before any of the app components can run, we
417 // launch the review activity and pass a pending intent to start the activity
418 // we are to launching now after the review is completed.
419 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
420 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
421 aInfo.packageName, userId)) {
422 IIntentSender target = mService.getIntentSenderLocked(
423 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
424 callingUid, userId, null, null, 0, new Intent[]{intent},
425 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
426 | PendingIntent.FLAG_ONE_SHOT, null);
428 final int flags = intent.getFlags();
429 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
430 newIntent.setFlags(flags
431 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
432 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
433 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
434 if (resultRecord != null) {
435 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
440 callingUid = realCallingUid;
441 callingPid = realCallingPid;
443 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
444 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
445 null /*profilerInfo*/);
447 if (DEBUG_PERMISSIONS_REVIEW) {
448 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
449 true, false) + "} from uid " + callingUid + " on display "
450 + (container == null ? (mSupervisor.mFocusedStack == null ?
451 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
452 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
453 container.mActivityDisplay.mDisplayId)));
458 // If we have an ephemeral app, abort the process of launching the resolved intent.
459 // Instead, launch the ephemeral installer. Once the installer is finished, it
460 // starts either the intent we resolved here [on install error] or the ephemeral
461 // app [on install success].
462 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
463 intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
464 rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
467 callingUid = realCallingUid;
468 callingPid = realCallingPid;
470 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
473 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
474 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
475 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
476 options, sourceRecord);
477 if (outActivity != null) {
481 if (r.appTimeTracker == null && sourceRecord != null) {
482 // If the caller didn't specify an explicit time tracker, we want to continue
483 // tracking under any it has.
484 r.appTimeTracker = sourceRecord.appTimeTracker;
487 final ActivityStack stack = mSupervisor.mFocusedStack;
488 if (voiceSession == null && (stack.mResumedActivity == null
489 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
490 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
491 realCallingPid, realCallingUid, "Activity start")) {
492 PendingActivityLaunch pal = new PendingActivityLaunch(r,
493 sourceRecord, startFlags, stack, callerApp);
494 mPendingActivityLaunches.add(pal);
495 ActivityOptions.abort(options);
496 return ActivityManager.START_SWITCHES_CANCELED;
500 if (mService.mDidAppSwitch) {
501 // This is the second allowed switch since we stopped switches,
502 // so now just generally allow switches. Use case: user presses
503 // home (switches disabled, switch to home, mDidAppSwitch now true);
504 // user taps a home icon (coming from home so allowed, we hit here
505 // and now allow anyone to switch again).
506 mService.mAppSwitchesAllowedTime = 0;
508 mService.mDidAppSwitch = true;
511 doPendingActivityLaunchesLocked(false);
514 mService.mWindowManager.deferSurfaceLayout();
515 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
516 true, options, inTask);
518 mService.mWindowManager.continueSurfaceLayout();
520 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
525 * Builds and returns an intent to launch the ephemeral installer.
527 private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
528 String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
529 final Intent nonEphemeralIntent = new Intent(origIntent);
530 nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
531 // Intent that is launched if the ephemeral package couldn't be installed
533 final IIntentSender failureIntentTarget = mService.getIntentSenderLocked(
534 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
535 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1,
536 new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType },
537 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
538 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
540 final Intent ephemeralIntent;
541 if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
542 // Force the intent to be directed to the ephemeral package
543 ephemeralIntent = new Intent(origIntent);
544 ephemeralIntent.setPackage(ephemeralPackage);
546 // Success intent goes back to the installer
547 ephemeralIntent = new Intent(launchIntent);
550 // Intent that is eventually launched if the ephemeral package was
551 // installed successfully. This will actually be launched by a platform
552 // broadcast receiver.
553 final IIntentSender successIntentTarget = mService.getIntentSenderLocked(
554 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
555 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0,
556 new Intent[]{ ephemeralIntent }, new String[]{ resolvedType },
557 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
558 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
560 // Finally build the actual intent to launch the ephemeral installer
561 int flags = launchIntent.getFlags();
562 final Intent intent = new Intent();
563 intent.setFlags(flags
564 | Intent.FLAG_ACTIVITY_NEW_TASK
565 | Intent.FLAG_ACTIVITY_CLEAR_TASK
566 | Intent.FLAG_ACTIVITY_NO_HISTORY
567 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
568 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
569 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
570 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
571 // TODO: Remove when the platform has fully implemented ephemeral apps
572 intent.setData(origIntent.getData().buildUpon().clearQuery().build());
576 void postStartActivityUncheckedProcessing(
577 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
578 ActivityStack targetStack) {
580 if (result < START_SUCCESS) {
581 // If someone asked to have the keyguard dismissed on the next activity start,
582 // but we are not actually doing an activity switch... just dismiss the keyguard now,
583 // because we probably want to see whatever is behind it.
584 mSupervisor.notifyActivityDrawnForKeyguard();
588 // We're waiting for an activity launch to finish, but that activity simply
589 // brought another activity to front. Let startActivityMayWait() know about
590 // this, so it waits for the new activity to become visible instead.
591 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
592 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
595 int startedActivityStackId = INVALID_STACK_ID;
596 if (r.task != null && r.task.stack != null) {
597 startedActivityStackId = r.task.stack.mStackId;
598 } else if (mTargetStack != null) {
599 startedActivityStackId = targetStack.mStackId;
602 // If we launched the activity from a no display activity that was launched from the home
603 // screen, we also need to start recents to un-minimize the docked stack, since the
604 // noDisplay activity will be finished shortly after.
605 // Note that some apps have trampoline activities without noDisplay being set. In that case,
606 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
607 // that tries to detect that case.
608 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
609 // visibility instead of using this flag.
610 final boolean noDisplayActivityOverHome = sourceRecord != null
611 && sourceRecord.noDisplay
612 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
613 if (startedActivityStackId == DOCKED_STACK_ID
614 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
615 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
616 final ActivityRecord topActivityHomeStack = homeStack != null
617 ? homeStack.topRunningActivityLocked() : null;
618 if (topActivityHomeStack == null
619 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
620 // We launch an activity while being in home stack, which means either launcher or
621 // recents into docked stack. We don't want the launched activity to be alone in a
622 // docked stack, so we want to immediately launch recents too.
623 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
624 mWindowManager.showRecentApps(true /* fromHome */);
629 if (startedActivityStackId == PINNED_STACK_ID
630 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
631 // The activity was already running in the pinned stack so it wasn't started, but either
632 // brought to the front or the new intent was delivered to it since it was already in
633 // front. Notify anyone interested in this piece of information.
634 mService.notifyPinnedActivityRestartAttemptLocked();
639 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
640 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
641 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
642 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
643 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
644 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
645 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
646 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
647 null /*container*/, null /*inTask*/);
648 if (mSupervisor.inResumeTopActivity) {
649 // If we are in resume section already, home activity will be initialized, but not
650 // resumed (to avoid recursive resume) and will stay that way until something pokes it
651 // again. We need to schedule another resume.
652 mSupervisor.scheduleResumeTopActivities();
656 void showConfirmDeviceCredential(int userId) {
657 // First, retrieve the stack that we want to resume after credential is confirmed.
658 ActivityStack targetStack;
659 ActivityStack fullscreenStack =
660 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
661 ActivityStack freeformStack =
662 mSupervisor.getStack(FREEFORM_WORKSPACE_STACK_ID);
663 if (fullscreenStack != null &&
664 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
665 // Single window case and the case that the docked stack is shown with fullscreen stack.
666 targetStack = fullscreenStack;
667 } else if (freeformStack != null &&
668 freeformStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
669 targetStack = freeformStack;
671 // The case that the docked stack is shown with recent.
672 targetStack = mSupervisor.getStack(HOME_STACK_ID);
674 if (targetStack == null) {
677 final KeyguardManager km = (KeyguardManager) mService.mContext
678 .getSystemService(Context.KEYGUARD_SERVICE);
679 final Intent credential =
680 km.createConfirmDeviceCredentialIntent(null, null, userId);
681 // For safety, check null here in case users changed the setting after the checking.
682 if (credential == null) {
685 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
686 if (activityRecord != null) {
687 final IIntentSender target = mService.getIntentSenderLocked(
688 ActivityManager.INTENT_SENDER_ACTIVITY,
689 activityRecord.launchedFromPackage,
690 activityRecord.launchedFromUid,
691 activityRecord.userId,
693 new Intent[] { activityRecord.intent },
694 new String[] { activityRecord.resolvedType },
695 PendingIntent.FLAG_CANCEL_CURRENT |
696 PendingIntent.FLAG_ONE_SHOT |
697 PendingIntent.FLAG_IMMUTABLE,
699 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
700 // Show confirm credentials activity.
701 startConfirmCredentialIntent(credential);
705 void startConfirmCredentialIntent(Intent intent) {
706 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
707 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
708 FLAG_ACTIVITY_TASK_ON_HOME);
709 final ActivityOptions options = ActivityOptions.makeBasic();
710 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
711 mService.mContext.startActivityAsUser(intent, options.toBundle(),
715 final int startActivityMayWait(IApplicationThread caller, int callingUid,
716 String callingPackage, Intent intent, String resolvedType,
717 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
718 IBinder resultTo, String resultWho, int requestCode, int startFlags,
719 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
720 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
721 IActivityContainer iContainer, TaskRecord inTask) {
722 // Refuse possible leaked file descriptors
723 if (intent != null && intent.hasFileDescriptors()) {
724 throw new IllegalArgumentException("File descriptors passed in Intent");
726 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
727 boolean componentSpecified = intent.getComponent() != null;
729 // Save a copy in case ephemeral needs it
730 final Intent ephemeralIntent = new Intent(intent);
731 // Don't modify the client's object!
732 intent = new Intent(intent);
734 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
736 UserInfo userInfo = mSupervisor.getUserInfo(userId);
737 if (userInfo != null && userInfo.isManagedProfile()) {
738 // Special case for managed profiles, if attempting to launch non-cryto aware
739 // app in a locked managed profile from an unlocked parent allow it to resolve
740 // as user will be sent via confirm credentials to unlock the profile.
741 UserManager userManager = UserManager.get(mService.mContext);
742 boolean profileLockedAndParentUnlockingOrUnlocked = false;
743 long token = Binder.clearCallingIdentity();
745 UserInfo parent = userManager.getProfileParent(userId);
746 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
747 && userManager.isUserUnlockingOrUnlocked(parent.id)
748 && !userManager.isUserUnlockingOrUnlocked(userId);
750 Binder.restoreCallingIdentity(token);
752 if (profileLockedAndParentUnlockingOrUnlocked) {
753 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
754 PackageManager.MATCH_DIRECT_BOOT_AWARE
755 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
759 // Collect information about the target of the Intent.
760 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
762 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
763 ActivityStackSupervisor.ActivityContainer container =
764 (ActivityStackSupervisor.ActivityContainer)iContainer;
765 synchronized (mService) {
766 if (container != null && container.mParentActivity != null &&
767 container.mParentActivity.state != RESUMED) {
768 // Cannot start a child activity if the parent is not resumed.
769 return ActivityManager.START_CANCELED;
771 final int realCallingPid = Binder.getCallingPid();
772 final int realCallingUid = Binder.getCallingUid();
774 if (callingUid >= 0) {
776 } else if (caller == null) {
777 callingPid = realCallingPid;
778 callingUid = realCallingUid;
780 callingPid = callingUid = -1;
783 final ActivityStack stack;
784 if (container == null || container.mStack.isOnHomeDisplay()) {
785 stack = mSupervisor.mFocusedStack;
787 stack = container.mStack;
789 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
790 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
791 "Starting activity when config will change = " + stack.mConfigWillChange);
793 final long origId = Binder.clearCallingIdentity();
796 (aInfo.applicationInfo.privateFlags
797 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
798 // This may be a heavy-weight process! Check to see if we already
799 // have another, different heavy-weight process running.
800 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
801 final ProcessRecord heavy = mService.mHeavyWeightProcess;
802 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
803 || !heavy.processName.equals(aInfo.processName))) {
804 int appCallingUid = callingUid;
805 if (caller != null) {
806 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
807 if (callerApp != null) {
808 appCallingUid = callerApp.info.uid;
810 Slog.w(TAG, "Unable to find app for caller " + caller
811 + " (pid=" + callingPid + ") when starting: "
812 + intent.toString());
813 ActivityOptions.abort(options);
814 return ActivityManager.START_PERMISSION_DENIED;
818 IIntentSender target = mService.getIntentSenderLocked(
819 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
820 appCallingUid, userId, null, null, 0, new Intent[] { intent },
821 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
822 | PendingIntent.FLAG_ONE_SHOT, null);
824 Intent newIntent = new Intent();
825 if (requestCode >= 0) {
826 // Caller is requesting a result.
827 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
829 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
830 new IntentSender(target));
831 if (heavy.activities.size() > 0) {
832 ActivityRecord hist = heavy.activities.get(0);
833 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
835 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
838 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
840 newIntent.setFlags(intent.getFlags());
841 newIntent.setClassName("android",
842 HeavyWeightSwitcherActivity.class.getName());
846 callingUid = Binder.getCallingUid();
847 callingPid = Binder.getCallingPid();
848 componentSpecified = true;
849 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
850 aInfo = rInfo != null ? rInfo.activityInfo : null;
852 aInfo = mService.getActivityInfoForUser(aInfo, userId);
858 final ActivityRecord[] outRecord = new ActivityRecord[1];
859 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
860 aInfo, rInfo, voiceSession, voiceInteractor,
861 resultTo, resultWho, requestCode, callingPid,
862 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
863 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
866 Binder.restoreCallingIdentity(origId);
868 if (stack.mConfigWillChange) {
869 // If the caller also wants to switch to a new configuration,
870 // do so now. This allows a clean switch, as we are waiting
871 // for the current activity to pause (so we will not destroy
872 // it), and have not yet started the next activity.
873 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
874 "updateConfiguration()");
875 stack.mConfigWillChange = false;
876 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
877 "Updating to new configuration after starting activity.");
878 mService.updateConfigurationLocked(config, null, false);
881 if (outResult != null) {
882 outResult.result = res;
883 if (res == ActivityManager.START_SUCCESS) {
884 mSupervisor.mWaitingActivityLaunched.add(outResult);
888 } catch (InterruptedException e) {
890 } while (outResult.result != START_TASK_TO_FRONT
891 && !outResult.timeout && outResult.who == null);
892 if (outResult.result == START_TASK_TO_FRONT) {
893 res = START_TASK_TO_FRONT;
896 if (res == START_TASK_TO_FRONT) {
897 ActivityRecord r = stack.topRunningActivityLocked();
898 if (r.nowVisible && r.state == RESUMED) {
899 outResult.timeout = false;
900 outResult.who = new ComponentName(r.info.packageName, r.info.name);
901 outResult.totalTime = 0;
902 outResult.thisTime = 0;
904 outResult.thisTime = SystemClock.uptimeMillis();
905 mSupervisor.mWaitingActivityVisible.add(outResult);
909 } catch (InterruptedException e) {
911 } while (!outResult.timeout && outResult.who == null);
916 final ActivityRecord launchedActivity = mReusedActivity != null
917 ? mReusedActivity : outRecord[0];
918 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
923 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
924 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
925 Bundle bOptions, int userId) {
926 if (intents == null) {
927 throw new NullPointerException("intents is null");
929 if (resolvedTypes == null) {
930 throw new NullPointerException("resolvedTypes is null");
932 if (intents.length != resolvedTypes.length) {
933 throw new IllegalArgumentException("intents are length different than resolvedTypes");
936 final int realCallingPid = Binder.getCallingPid();
937 final int realCallingUid = Binder.getCallingUid();
940 if (callingUid >= 0) {
942 } else if (caller == null) {
943 callingPid = realCallingPid;
944 callingUid = realCallingUid;
946 callingPid = callingUid = -1;
948 final long origId = Binder.clearCallingIdentity();
950 synchronized (mService) {
951 ActivityRecord[] outActivity = new ActivityRecord[1];
952 for (int i=0; i<intents.length; i++) {
953 Intent intent = intents[i];
954 if (intent == null) {
958 // Refuse possible leaked file descriptors
959 if (intent != null && intent.hasFileDescriptors()) {
960 throw new IllegalArgumentException("File descriptors passed in Intent");
963 boolean componentSpecified = intent.getComponent() != null;
965 // Don't modify the client's object!
966 intent = new Intent(intent);
968 // Collect information about the target of the Intent.
969 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
971 // TODO: New, check if this is correct
972 aInfo = mService.getActivityInfoForUser(aInfo, userId);
975 (aInfo.applicationInfo.privateFlags
976 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
977 throw new IllegalArgumentException(
978 "FLAG_CANT_SAVE_STATE not supported here");
981 ActivityOptions options = ActivityOptions.fromBundle(
982 i == intents.length - 1 ? bOptions : null);
983 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
984 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
985 callingPid, callingUid, callingPackage,
986 realCallingPid, realCallingUid, 0,
987 options, false, componentSpecified, outActivity, null, null);
992 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
996 Binder.restoreCallingIdentity(origId);
999 return START_SUCCESS;
1002 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
1003 // Trigger launch power hint if activity being launched is not in the current task
1004 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1005 final ActivityRecord curTop = (focusStack == null)
1006 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1007 if ((forceSend || (!mPowerHintSent && curTop != null &&
1008 curTop.task != null && mStartActivity != null &&
1009 curTop.task != mStartActivity.task )) &&
1010 mService.mLocalPowerManager != null) {
1011 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
1012 mPowerHintSent = true;
1016 void sendPowerHintForLaunchEndIfNeeded() {
1017 // Trigger launch power hint if activity is launched
1018 if (mPowerHintSent && mService.mLocalPowerManager != null) {
1019 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
1020 mPowerHintSent = false;
1024 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1025 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1026 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1028 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1031 computeLaunchingTaskFlags();
1033 computeSourceStack();
1035 mIntent.setFlags(mLaunchFlags);
1037 mReusedActivity = getReusableIntentActivity();
1039 final int preferredLaunchStackId =
1040 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1042 if (mReusedActivity != null) {
1043 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1044 // still needs to be a lock task mode violation since the task gets cleared out and
1045 // the device would otherwise leave the locked task.
1046 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
1047 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1048 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1049 mSupervisor.showLockTaskToast();
1050 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1051 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1054 if (mStartActivity.task == null) {
1055 mStartActivity.task = mReusedActivity.task;
1057 if (mReusedActivity.task.intent == null) {
1058 // This task was started because of movement of the activity based on affinity...
1059 // Now that we are actually launching it, we can assign the base intent.
1060 mReusedActivity.task.setIntent(mStartActivity);
1063 // This code path leads to delivering a new intent, we want to make sure we schedule it
1064 // as the first operation, in case the activity will be resumed as a result of later
1066 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1067 || mLaunchSingleInstance || mLaunchSingleTask) {
1068 // In this situation we want to remove all activities from the task up to the one
1069 // being started. In most cases this means we are resetting the task to its initial
1071 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
1072 mStartActivity, mLaunchFlags);
1074 if (top.frontOfTask) {
1075 // Activity aliases may mean we use different intents for the top activity,
1076 // so make sure the task now has the identity of the new intent.
1077 top.task.setIntent(mStartActivity);
1079 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1080 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1081 mStartActivity.launchedFromPackage);
1085 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1087 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
1089 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1090 // We don't need to start a new activity, and the client said not to do anything
1091 // if that is the case, so this is it! And for paranoia, make sure we have
1092 // correctly resumed the top activity.
1093 resumeTargetStackIfNeeded();
1094 return START_RETURN_INTENT_TO_CALLER;
1096 setTaskFromIntentActivity(mReusedActivity);
1098 if (!mAddingToTask && mReuseTask == null) {
1099 // We didn't do anything... but it was needed (a.k.a., client don't use that
1100 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1101 resumeTargetStackIfNeeded();
1102 return START_TASK_TO_FRONT;
1106 if (mStartActivity.packageName == null) {
1107 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1108 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1109 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1110 mStartActivity.requestCode, RESULT_CANCELED, null);
1112 ActivityOptions.abort(mOptions);
1113 return START_CLASS_NOT_FOUND;
1116 // If the activity being launched is the same as the one currently at the top, then
1117 // we need to check if it should only be launched once.
1118 final ActivityStack topStack = mSupervisor.mFocusedStack;
1119 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1120 final boolean dontStart = top != null && mStartActivity.resultTo == null
1121 && top.realActivity.equals(mStartActivity.realActivity)
1122 && top.userId == mStartActivity.userId
1123 && top.app != null && top.app.thread != null
1124 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1125 || mLaunchSingleTop || mLaunchSingleTask);
1127 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1128 // For paranoia, make sure we have correctly resumed the top activity.
1129 topStack.mLastPausedActivity = null;
1131 mSupervisor.resumeFocusedStackTopActivityLocked();
1133 ActivityOptions.abort(mOptions);
1134 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1135 // We don't need to start a new activity, and the client said not to do
1136 // anything if that is the case, so this is it!
1137 return START_RETURN_INTENT_TO_CALLER;
1139 top.deliverNewIntentLocked(
1140 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1142 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1143 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1144 mSupervisor.handleNonResizableTaskIfNeeded(
1145 top.task, preferredLaunchStackId, topStack.mStackId);
1147 return START_DELIVERED_TO_TOP;
1150 boolean newTask = false;
1151 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1152 ? mSourceRecord.task : null;
1154 // Should this be considered a new task?
1155 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1156 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1158 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1160 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1161 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1162 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1164 if (!mMovedOtherTask) {
1165 // If stack id is specified in activity options, usually it means that activity is
1166 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1167 // that case we check the target stack.
1168 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1169 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1171 } else if (mSourceRecord != null) {
1172 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1173 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1174 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1177 final int result = setTaskFromSourceRecord();
1178 if (result != START_SUCCESS) {
1181 } else if (mInTask != null) {
1182 // The caller is asking that the new activity be started in an explicit
1183 // task it has provided to us.
1184 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1185 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1186 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1189 final int result = setTaskFromInTask();
1190 if (result != START_SUCCESS) {
1194 // This not being started from an existing activity, and not part of a new task...
1195 // just put it in the top task, though these days this case should never happen.
1196 setTaskToCurrentTopOrCreateNewTask();
1199 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1200 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1202 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1203 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1206 EventLog.writeEvent(
1207 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1209 ActivityStack.logStartActivity(
1210 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1211 mTargetStack.mLastPausedActivity = null;
1213 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
1215 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1217 if (!mLaunchTaskBehind) {
1218 // TODO(b/26381750): Remove this code after verification that all the decision
1219 // points above moved targetStack to the front which will also set the focus
1221 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1223 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1224 if (!mTargetStack.isFocusable()
1225 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1226 && mStartActivity != topTaskActivity)) {
1227 // If the activity is not focusable, we can't resume it, but still would like to
1228 // make sure it becomes visible as it starts (this will also trigger entry
1229 // animation). An example of this are PIP activities.
1230 // Also, we don't want to resume activities in a task that currently has an overlay
1231 // as the starting activity just needs to be in the visible paused state until the
1233 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1234 // Go ahead and tell window manager to execute app transition for this activity
1235 // since the app transition will not be triggered through the resume channel.
1236 mWindowManager.executeAppTransition();
1238 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1242 mTargetStack.addRecentActivityLocked(mStartActivity);
1244 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1246 mSupervisor.handleNonResizableTaskIfNeeded(
1247 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
1249 return START_SUCCESS;
1252 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1253 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1254 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1260 mCallingUid = r.launchedFromUid;
1261 mSourceRecord = sourceRecord;
1262 mVoiceSession = voiceSession;
1263 mVoiceInteractor = voiceInteractor;
1265 mLaunchBounds = getOverrideBounds(r, options, inTask);
1267 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1268 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1269 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1270 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1271 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1272 mLaunchTaskBehind = r.mLaunchTaskBehind
1273 && !mLaunchSingleTask && !mLaunchSingleInstance
1274 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1276 sendNewTaskResultRequestIfNeeded();
1278 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1279 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1282 // If we are actually going to launch in to a new task, there are some cases where
1283 // we further want to do multiple task.
1284 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1285 if (mLaunchTaskBehind
1286 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1287 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1291 // We'll invoke onUserLeaving before onPause only if the launching
1292 // activity did not explicitly state that this is an automated launch.
1293 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1294 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1295 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1297 // If the caller has asked not to resume at this point, we make note
1298 // of this in the record so that we can skip it when trying to find
1299 // the top running activity.
1300 mDoResume = doResume;
1301 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1302 r.delayedResume = true;
1306 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1307 r.mTaskOverlay = true;
1308 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1309 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1310 if (top != null && !top.visible) {
1312 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1315 mAvoidMoveToFront = true;
1319 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1322 // In some flows in to this function, we retrieve the task record and hold on to it
1323 // without a lock before calling back in to here... so the task at this point may
1324 // not actually be in recents. Check for that, and if it isn't in recents just
1325 // consider it invalid.
1326 if (inTask != null && !inTask.inRecents) {
1327 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1331 mStartFlags = startFlags;
1332 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1333 // is the same as the one making the call... or, as a special case, if we do not know
1334 // the caller then we count the current top activity as the caller.
1335 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1336 ActivityRecord checkedCaller = sourceRecord;
1337 if (checkedCaller == null) {
1338 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1341 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1342 // Caller is not the same as launcher, so always needed.
1343 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1347 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1350 private void sendNewTaskResultRequestIfNeeded() {
1351 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1352 && mStartActivity.resultTo.task.stack != null) {
1353 // For whatever reason this activity is being launched into a new task...
1354 // yet the caller has requested a result back. Well, that is pretty messed up,
1355 // so instead immediately send back a cancel and let the new task continue launched
1356 // as normal without a dependency on its originator.
1357 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1358 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1359 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1360 mStartActivity.resultTo = null;
1364 private void computeLaunchingTaskFlags() {
1365 // If the caller is not coming from another activity, but has given us an explicit task into
1366 // which they would like us to launch the new activity, then let's see about doing that.
1367 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1368 final Intent baseIntent = mInTask.getBaseIntent();
1369 final ActivityRecord root = mInTask.getRootActivity();
1370 if (baseIntent == null) {
1371 ActivityOptions.abort(mOptions);
1372 throw new IllegalArgumentException("Launching into task without base intent: "
1376 // If this task is empty, then we are adding the first activity -- it
1377 // determines the root, and must be launching as a NEW_TASK.
1378 if (mLaunchSingleInstance || mLaunchSingleTask) {
1379 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1380 ActivityOptions.abort(mOptions);
1381 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1382 + mStartActivity + " into different task " + mInTask);
1385 ActivityOptions.abort(mOptions);
1386 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1387 + " has root " + root + " but target is singleInstance/Task");
1391 // If task is empty, then adopt the interesting intent launch flags in to the
1392 // activity being started.
1394 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1395 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1396 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1397 | (baseIntent.getFlags() & flagsOfInterest);
1398 mIntent.setFlags(mLaunchFlags);
1399 mInTask.setIntent(mStartActivity);
1400 mAddingToTask = true;
1402 // If the task is not empty and the caller is asking to start it as the root of
1403 // a new task, then we don't actually want to start this on the task. We will
1404 // bring the task to the front, and possibly give it a new intent.
1405 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1406 mAddingToTask = false;
1409 mAddingToTask = true;
1412 mReuseTask = mInTask;
1415 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1416 // when in freeform workspace.
1417 // Also put noDisplay activities in the source task. These by itself can be placed
1418 // in any task/stack, however it could launch other activities like ResolverActivity,
1419 // and we want those to stay in the original task.
1420 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1421 && mSourceRecord.isFreeform()) {
1422 mAddingToTask = true;
1426 if (mInTask == null) {
1427 if (mSourceRecord == null) {
1428 // This activity is not being started from another... in this
1429 // case we -always- start a new task.
1430 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1431 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1432 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1433 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1435 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1436 // The original activity who is starting us is running as a single
1437 // instance... this new activity it is starting must go on its
1439 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1440 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1441 // The activity being started is a single instance... it always
1442 // gets launched into its own task.
1443 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1448 private void computeSourceStack() {
1449 if (mSourceRecord == null) {
1450 mSourceStack = null;
1453 if (!mSourceRecord.finishing) {
1454 mSourceStack = mSourceRecord.task.stack;
1458 // If the source is finishing, we can't further count it as our source. This is because the
1459 // task it is associated with may now be empty and on its way out, so we don't want to
1460 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1461 // a task for it. But save the task information so it can be used when creating the new task.
1462 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1463 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1464 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1465 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1466 mNewTaskInfo = mSourceRecord.info;
1467 mNewTaskIntent = mSourceRecord.task.intent;
1469 mSourceRecord = null;
1470 mSourceStack = null;
1474 * Decide whether the new activity should be inserted into an existing task. Returns null
1475 * if not or an ActivityRecord with the task into which the new activity should be added.
1477 private ActivityRecord getReusableIntentActivity() {
1478 // We may want to try to place the new activity in to an existing task. We always
1479 // do this if the target activity is singleTask or singleInstance; we will also do
1480 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1481 // us to still place it in a new task: multi task, always doc mode, or being asked to
1482 // launch this as a new task behind the current one.
1483 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1484 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1485 || mLaunchSingleInstance || mLaunchSingleTask;
1486 // If bring to front is requested, and no result is requested and we have not been given
1487 // an explicit task to launch in to, and we can find a task that was started with this
1488 // same component, then instead of launching bring that one to the front.
1489 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1490 ActivityRecord intentActivity = null;
1491 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1492 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1493 intentActivity = task != null ? task.getTopActivity() : null;
1494 } else if (putIntoExistingTask) {
1495 if (mLaunchSingleInstance) {
1496 // There can be one and only one instance of single instance activity in the
1497 // history, and it is always in its own unique task, so we do a special search.
1498 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
1499 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1500 // For the launch adjacent case we only want to put the activity in an existing
1501 // task if the activity already exists in the history.
1502 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1503 !mLaunchSingleTask);
1505 // Otherwise find the best task to put the activity in.
1506 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1509 return intentActivity;
1512 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1513 mTargetStack = intentActivity.task.stack;
1514 mTargetStack.mLastPausedActivity = null;
1515 // If the target task is not in the front, then we need to bring it to the front...
1516 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1517 // the same behavior as if a new instance was being started, which means not bringing it
1518 // to the front if the caller is not itself in the front.
1519 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1520 ActivityRecord curTop = (focusStack == null)
1521 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1524 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1525 && !mAvoidMoveToFront) {
1526 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1527 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1528 mSourceStack.topActivity().task == mSourceRecord.task)) {
1529 // We really do want to push this one into the user's face, right now.
1530 if (mLaunchTaskBehind && mSourceRecord != null) {
1531 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1533 mMovedOtherTask = true;
1535 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1536 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1537 // So no point resuming any of the activities here, it just wastes one extra
1538 // resuming, plus enter AND exit transitions.
1539 // Here we only want to bring the target stack forward. Transition will be applied
1540 // to the new activity that's started after the old ones are gone.
1541 final boolean willClearTask =
1542 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1543 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1544 if (!willClearTask) {
1545 final ActivityStack launchStack = getLaunchStack(
1546 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
1547 if (launchStack == null || launchStack == mTargetStack) {
1548 // We only want to move to the front, if we aren't going to launch on a
1549 // different stack. If we launch on a different stack, we will put the
1550 // task on top there.
1551 mTargetStack.moveTaskToFrontLocked(
1552 intentActivity.task, mNoAnimation, mOptions,
1553 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1554 mMovedToFront = true;
1555 } else if (launchStack.mStackId == DOCKED_STACK_ID
1556 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1557 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1558 // If we want to launch adjacent and mTargetStack is not the computed
1559 // launch stack - move task to top of computed stack.
1560 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1561 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1564 // TODO: This should be reevaluated in MW v2.
1565 // We choose to move task to front instead of launching it adjacent
1566 // when specific stack was requested explicitly and it appeared to be
1567 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1568 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1569 mOptions, mStartActivity.appTimeTracker,
1570 "bringToFrontInsteadOfAdjacentLaunch");
1572 mMovedToFront = true;
1576 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
1579 if (!mMovedToFront && mDoResume) {
1580 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1581 + " from " + intentActivity);
1582 mTargetStack.moveToFront("intentActivityFound");
1585 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1586 mTargetStack.mStackId);
1588 // If the caller has requested that the target task be reset, then do so.
1589 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1590 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1592 return intentActivity;
1595 private void updateTaskReturnToType(
1596 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1597 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1598 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1599 // Caller wants to appear on home activity.
1600 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1602 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1603 // Task will be launched over the home stack, so return home.
1604 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1608 // Else we are coming from an application stack so return to an application.
1609 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1612 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1613 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1614 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1615 // The caller has requested to completely replace any existing task with its new
1616 // activity. Well that should not be too hard...
1617 mReuseTask = intentActivity.task;
1618 mReuseTask.performClearTaskLocked();
1619 mReuseTask.setIntent(mStartActivity);
1620 // When we clear the task - focus will be adjusted, which will bring another task
1621 // to top before we launch the activity we need. This will temporary swap their
1622 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1623 mMovedOtherTask = true;
1624 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1625 || mLaunchSingleInstance || mLaunchSingleTask) {
1626 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1629 // A special case: we need to start the activity because it is not currently
1630 // running, and the caller has asked to clear the current task to have this
1631 // activity at the top.
1632 mAddingToTask = true;
1633 // Now pretend like this activity is being started by the top of its task, so it
1634 // is put in the right place.
1635 mSourceRecord = intentActivity;
1636 final TaskRecord task = mSourceRecord.task;
1637 if (task != null && task.stack == null) {
1638 // Target stack got cleared when we all activities were removed above.
1639 // Go ahead and reset it.
1640 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1641 null /* bounds */, mLaunchFlags, mOptions);
1642 mTargetStack.addTask(task,
1643 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1646 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1647 // In this case the top activity on the task is the same as the one being launched,
1648 // so we take that as a request to bring the task to the foreground. If the top
1649 // activity in the task is the root activity, deliver this new intent to it if it
1651 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1652 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
1653 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
1654 intentActivity.task);
1655 if (intentActivity.frontOfTask) {
1656 intentActivity.task.setIntent(mStartActivity);
1658 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1659 mStartActivity.launchedFromPackage);
1660 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
1661 // In this case we are launching the root activity of the task, but with a
1662 // different intent. We should start a new instance on top.
1663 mAddingToTask = true;
1664 mSourceRecord = intentActivity;
1666 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1667 // In this case an activity is being launched in to an existing task, without
1668 // resetting that task. This is typically the situation of launching an activity
1669 // from a notification or shortcut. We want to place the new activity on top of the
1671 mAddingToTask = true;
1672 mSourceRecord = intentActivity;
1673 } else if (!intentActivity.task.rootWasReset) {
1674 // In this case we are launching into an existing task that has not yet been started
1675 // from its front door. The current task has been brought to the front. Ideally,
1676 // we'd probably like to place this new task at the bottom of its stack, but that's
1677 // a little hard to do with the current organization of the code so for now we'll
1679 intentActivity.task.setIntent(mStartActivity);
1683 private void resumeTargetStackIfNeeded() {
1685 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1686 if (!mMovedToFront) {
1687 // Make sure to notify Keyguard as well if we are not running an app transition
1689 mSupervisor.notifyActivityDrawnForKeyguard();
1692 ActivityOptions.abort(mOptions);
1694 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1697 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1698 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1701 if (mReuseTask == null) {
1702 final TaskRecord task = mTargetStack.createTaskRecord(
1703 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1704 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1705 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1706 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1707 mStartActivity.setTask(task, taskToAffiliate);
1708 if (mLaunchBounds != null) {
1709 final int stackId = mTargetStack.mStackId;
1710 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1711 mService.resizeStack(
1712 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1714 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1717 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1718 "Starting new activity " +
1719 mStartActivity + " in new task " + mStartActivity.task);
1721 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1725 private int setTaskFromSourceRecord() {
1726 final TaskRecord sourceTask = mSourceRecord.task;
1727 // We only want to allow changing stack if the target task is not the top one,
1728 // otherwise we would move the launching task to the other side, rather than show
1729 // two side by side.
1730 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1731 if (moveStackAllowed) {
1732 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1736 if (mTargetStack == null) {
1737 mTargetStack = sourceTask.stack;
1738 } else if (mTargetStack != sourceTask.stack) {
1739 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1740 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1743 mTargetStack.moveToFront("sourceStackToFront");
1745 final TaskRecord topTask = mTargetStack.topTask();
1746 if (topTask != sourceTask && !mAvoidMoveToFront) {
1747 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1748 mStartActivity.appTimeTracker, "sourceTaskToFront");
1750 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1751 // In this case, we are adding the activity to an existing task, but the caller has
1752 // asked to clear that task if the activity is already running.
1753 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1754 mKeepCurTransition = true;
1756 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1757 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1758 // For paranoia, make sure we have correctly resumed the top activity.
1759 mTargetStack.mLastPausedActivity = null;
1761 mSupervisor.resumeFocusedStackTopActivityLocked();
1763 ActivityOptions.abort(mOptions);
1764 return START_DELIVERED_TO_TOP;
1766 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1767 // In this case, we are launching an activity in our own task that may already be
1768 // running somewhere in the history, and we want to shuffle it to the front of the
1770 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1772 final TaskRecord task = top.task;
1773 task.moveActivityToFrontLocked(top);
1774 top.updateOptionsLocked(mOptions);
1775 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
1776 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1777 mTargetStack.mLastPausedActivity = null;
1779 mSupervisor.resumeFocusedStackTopActivityLocked();
1781 return START_DELIVERED_TO_TOP;
1785 // An existing activity is starting this new activity, so we want to keep the new one in
1786 // the same task as the one that is starting it.
1787 mStartActivity.setTask(sourceTask, null);
1788 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1789 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1790 return START_SUCCESS;
1793 private int setTaskFromInTask() {
1794 if (mLaunchBounds != null) {
1795 mInTask.updateOverrideConfiguration(mLaunchBounds);
1796 int stackId = mInTask.getLaunchStackId();
1797 if (stackId != mInTask.stack.mStackId) {
1798 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
1799 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1800 stackId = stack.mStackId;
1802 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1803 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1806 mTargetStack = mInTask.stack;
1807 mTargetStack.moveTaskToFrontLocked(
1808 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1810 // Check whether we should actually launch the new activity in to the task,
1811 // or just reuse the current activity on top.
1812 ActivityRecord top = mInTask.getTopActivity();
1813 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1814 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1815 || mLaunchSingleTop || mLaunchSingleTask) {
1816 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
1817 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1818 // We don't need to start a new activity, and the client said not to do
1819 // anything if that is the case, so this is it!
1820 return START_RETURN_INTENT_TO_CALLER;
1822 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1823 return START_DELIVERED_TO_TOP;
1827 if (!mAddingToTask) {
1828 // We don't actually want to have this activity added to the task, so just
1829 // stop here but still tell the caller that we consumed the intent.
1830 ActivityOptions.abort(mOptions);
1831 return START_TASK_TO_FRONT;
1834 mStartActivity.setTask(mInTask, null);
1835 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1836 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1838 return START_SUCCESS;
1841 private void setTaskToCurrentTopOrCreateNewTask() {
1842 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1845 mTargetStack.moveToFront("addingToTopTask");
1847 final ActivityRecord prev = mTargetStack.topActivity();
1848 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1849 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1850 mStartActivity.info, mIntent, null, null, true);
1851 mStartActivity.setTask(task, null);
1852 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1853 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1854 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1857 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1858 boolean launchSingleTask, int launchFlags) {
1859 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1860 (launchSingleInstance || launchSingleTask)) {
1861 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1862 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1863 "\"singleInstance\" or \"singleTask\"");
1865 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1867 switch (r.info.documentLaunchMode) {
1868 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1870 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1871 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1873 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1874 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1876 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1877 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1884 final void doPendingActivityLaunchesLocked(boolean doResume) {
1885 while (!mPendingActivityLaunches.isEmpty()) {
1886 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1887 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
1889 final int result = startActivityUnchecked(
1890 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1891 postStartActivityUncheckedProcessing(
1892 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1894 } catch (Exception e) {
1895 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1896 pal.sendErrorResult(e.getMessage());
1901 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1902 int launchFlags, ActivityOptions aOptions) {
1903 final TaskRecord task = r.task;
1904 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1905 return mSupervisor.mHomeStack;
1908 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
1909 if (stack != null) {
1913 if (task != null && task.stack != null) {
1915 if (stack.isOnHomeDisplay()) {
1916 if (mSupervisor.mFocusedStack != stack) {
1917 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1918 "computeStackFocus: Setting " + "focused stack to r=" + r
1921 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1922 "computeStackFocus: Focused stack already="
1923 + mSupervisor.mFocusedStack);
1929 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1930 if (container != null) {
1931 // The first time put it on the desired stack, after this put on task stack.
1932 r.mInitialActivityContainer = null;
1933 return container.mStack;
1936 // The fullscreen stack can contain any task regardless of if the task is resizeable
1937 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1938 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1939 // we can also put it in the focused stack.
1940 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1941 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1942 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1943 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
1944 if (canUseFocusedStack && (!newTask
1945 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1946 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1947 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1948 return mSupervisor.mFocusedStack;
1951 // We first try to put the task in the first dynamic stack.
1952 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1953 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1954 stack = homeDisplayStacks.get(stackNdx);
1955 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1956 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1957 "computeStackFocus: Setting focused stack=" + stack);
1962 // If there is no suitable dynamic stack then we figure out which static stack to use.
1963 final int stackId = task != null ? task.getLaunchStackId() :
1964 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1965 FULLSCREEN_WORKSPACE_STACK_ID;
1966 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1967 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1968 + r + " stackId=" + stack.mStackId);
1972 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1973 ActivityOptions aOptions) {
1975 // We are reusing a task, keep the stack!
1976 if (mReuseTask != null) {
1977 return mReuseTask.stack;
1980 final int launchStackId =
1981 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1983 if (isValidLaunchStackId(launchStackId, r)) {
1984 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
1985 } else if (launchStackId == DOCKED_STACK_ID) {
1986 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1987 // for this activity, so we put the activity in the fullscreen stack.
1988 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1991 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
1994 // Otherwise handle adjacent launch.
1996 // The parent activity doesn't want to launch the activity on top of itself, but
1997 // instead tries to put it onto other side in side-by-side mode.
1998 final ActivityStack parentStack = task != null ? task.stack
1999 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2000 : mSupervisor.mFocusedStack;
2002 if (parentStack != mSupervisor.mFocusedStack) {
2003 // If task's parent stack is not focused - use it during adjacent launch.
2006 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2007 // If task is already on top of focused stack - use it. We don't want to move the
2008 // existing focused task to adjacent stack, just deliver new intent in this case.
2009 return mSupervisor.mFocusedStack;
2012 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2013 // If parent was in docked stack, the natural place to launch another activity
2014 // will be fullscreen, so it can appear alongside the docked window.
2015 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2018 // If the parent is not in the docked stack, we check if there is docked window
2019 // and if yes, we will launch into that stack. If not, we just put the new
2020 // activity into parent's stack, because we can't find a better place.
2021 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2022 if (dockedStack != null
2023 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2024 // There is a docked stack, but it isn't visible, so we can't launch into that.
2033 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2034 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2035 || !StackId.isStaticStack(stackId)) {
2039 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2040 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2044 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2048 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2052 final boolean supportsPip = mService.mSupportsPictureInPicture
2053 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2054 if (stackId == PINNED_STACK_ID && !supportsPip) {
2060 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2061 Rect newBounds = null;
2062 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2063 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2064 options, options.getLaunchStackId())) {
2065 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
2071 void setWindowManager(WindowManagerService wm) {
2072 mWindowManager = wm;
2075 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2076 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2077 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2078 if (pal.stack == stack) {
2079 mPendingActivityLaunches.remove(palNdx);