ActivityStarter.java revision ea9b10e64419edbd5d3ed13f82007ffed97af418
1package com.android.server.am; 2 3import static android.app.Activity.RESULT_CANCELED; 4import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; 5import static android.app.ActivityManager.START_CLASS_NOT_FOUND; 6import static android.app.ActivityManager.START_DELIVERED_TO_TOP; 7import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED; 8import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER; 9import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; 10import static android.app.ActivityManager.START_SUCCESS; 11import static android.app.ActivityManager.START_TASK_TO_FRONT; 12import static android.app.ActivityManager.StackId; 13import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 14import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 15import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; 16import static android.app.ActivityManager.StackId.HOME_STACK_ID; 17import static android.app.ActivityManager.StackId.INVALID_STACK_ID; 18import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 19import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; 20import static android.app.PendingIntent.FLAG_IMMUTABLE; 21import static android.app.PendingIntent.FLAG_ONE_SHOT; 22import static android.content.Context.KEYGUARD_SERVICE; 23import static android.content.Intent.EXTRA_INTENT; 24import static android.content.Intent.EXTRA_PACKAGE_NAME; 25import static android.content.Intent.EXTRA_TASK_ID; 26import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; 27import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; 28import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; 29import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE; 30import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; 31import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; 32import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 33import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; 34import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; 35import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME; 36import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP; 37import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT; 38import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED; 39import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; 40import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP; 41import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS; 42import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; 43import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; 44import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP; 45import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; 46import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS; 47import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW; 48import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS; 49import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; 50import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; 51import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING; 52import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; 53import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS; 54import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS; 55import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING; 56import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 57import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 58import static com.android.server.am.ActivityManagerService.ANIMATE; 59import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; 60import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; 61import static com.android.server.am.ActivityStack.ActivityState.RESUMED; 62import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED; 63import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS; 64import static com.android.server.am.ActivityStackSupervisor.ON_TOP; 65import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS; 66 67import android.app.Activity; 68import android.app.ActivityManager; 69import android.app.ActivityOptions; 70import android.app.AppGlobals; 71import android.app.IActivityContainer; 72import android.app.IActivityManager; 73import android.app.IApplicationThread; 74import android.app.KeyguardManager; 75import android.app.PendingIntent; 76import android.app.ProfilerInfo; 77import android.content.ComponentName; 78import android.content.IIntentSender; 79import android.content.Intent; 80import android.content.IntentSender; 81import android.content.pm.ActivityInfo; 82import android.content.pm.ApplicationInfo; 83import android.content.pm.ResolveInfo; 84import android.content.pm.UserInfo; 85import android.content.res.Configuration; 86import android.graphics.Rect; 87import android.os.Binder; 88import android.os.Build; 89import android.os.Bundle; 90import android.os.IBinder; 91import android.os.RemoteException; 92import android.os.SystemClock; 93import android.os.UserHandle; 94import android.os.UserManager; 95import android.service.voice.IVoiceInteractionSession; 96import android.util.EventLog; 97import android.util.Slog; 98import android.view.Display; 99 100import com.android.internal.app.HeavyWeightSwitcherActivity; 101import com.android.internal.app.IVoiceInteractor; 102import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch; 103import com.android.server.wm.WindowManagerService; 104 105import java.util.ArrayList; 106 107/** 108 * Controller for interpreting how and then launching activities. 109 * 110 * This class collects all the logic for determining how an intent and flags should be turned into 111 * an activity and associated task and stack. 112 */ 113class ActivityStarter { 114 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM; 115 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS; 116 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS; 117 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; 118 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; 119 120 private final ActivityManagerService mService; 121 private final ActivityStackSupervisor mSupervisor; 122 private WindowManagerService mWindowManager; 123 124 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>(); 125 126 // Share state variable among methods when starting an activity. 127 private ActivityRecord mStartActivity; 128 private Intent mIntent; 129 private int mCallingUid; 130 private ActivityOptions mOptions; 131 132 private boolean mLaunchSingleTop; 133 private boolean mLaunchSingleInstance; 134 private boolean mLaunchSingleTask; 135 private boolean mLaunchTaskBehind; 136 private int mLaunchFlags; 137 138 private Rect mLaunchBounds; 139 140 private ActivityRecord mNotTop; 141 private boolean mDoResume; 142 private int mStartFlags; 143 private ActivityRecord mSourceRecord; 144 145 private TaskRecord mInTask; 146 private boolean mAddingToTask; 147 private TaskRecord mReuseTask; 148 149 private ActivityInfo mNewTaskInfo; 150 private Intent mNewTaskIntent; 151 private ActivityStack mSourceStack; 152 private ActivityStack mTargetStack; 153 // TODO: Is the mMoveHome flag really needed? 154 private boolean mMovedHome; 155 private boolean mMovedToFront; 156 private boolean mNoAnimation; 157 private boolean mKeepCurTransition; 158 159 private IVoiceInteractionSession mVoiceSession; 160 private IVoiceInteractor mVoiceInteractor; 161 162 private void reset() { 163 mStartActivity = null; 164 mIntent = null; 165 mCallingUid = -1; 166 mOptions = null; 167 168 mLaunchSingleTop = false; 169 mLaunchSingleInstance = false; 170 mLaunchSingleTask = false; 171 mLaunchTaskBehind = false; 172 mLaunchFlags = 0; 173 174 mLaunchBounds = null; 175 176 mNotTop = null; 177 mDoResume = false; 178 mStartFlags = 0; 179 mSourceRecord = null; 180 181 mInTask = null; 182 mAddingToTask = false; 183 mReuseTask = null; 184 185 mNewTaskInfo = null; 186 mNewTaskIntent = null; 187 mSourceStack = null; 188 189 mTargetStack = null; 190 mMovedHome = false; 191 mMovedToFront = false; 192 mNoAnimation = false; 193 mKeepCurTransition = false; 194 195 mVoiceSession = null; 196 mVoiceInteractor = null; 197 } 198 199 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) { 200 mService = service; 201 mSupervisor = supervisor; 202 } 203 204 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, 205 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, 206 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 207 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, 208 String callingPackage, int realCallingPid, int realCallingUid, int startFlags, 209 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, 210 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, 211 TaskRecord inTask) { 212 int err = ActivityManager.START_SUCCESS; 213 214 ProcessRecord callerApp = null; 215 if (caller != null) { 216 callerApp = mService.getRecordForAppLocked(caller); 217 if (callerApp != null) { 218 callingPid = callerApp.pid; 219 callingUid = callerApp.info.uid; 220 } else { 221 Slog.w(TAG, "Unable to find app for caller " + caller 222 + " (pid=" + callingPid + ") when starting: " 223 + intent.toString()); 224 err = ActivityManager.START_PERMISSION_DENIED; 225 } 226 } 227 228 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; 229 230 if (err == ActivityManager.START_SUCCESS) { 231 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) 232 + "} from uid " + callingUid 233 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ? 234 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) : 235 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY : 236 container.mActivityDisplay.mDisplayId))); 237 } 238 239 ActivityRecord sourceRecord = null; 240 ActivityRecord resultRecord = null; 241 if (resultTo != null) { 242 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo); 243 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, 244 "Will send result to " + resultTo + " " + sourceRecord); 245 if (sourceRecord != null) { 246 if (requestCode >= 0 && !sourceRecord.finishing) { 247 resultRecord = sourceRecord; 248 } 249 } 250 } 251 252 final int launchFlags = intent.getFlags(); 253 254 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { 255 // Transfer the result target from the source activity to the new 256 // one being started, including any failures. 257 if (requestCode >= 0) { 258 ActivityOptions.abort(options); 259 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; 260 } 261 resultRecord = sourceRecord.resultTo; 262 if (resultRecord != null && !resultRecord.isInStackLocked()) { 263 resultRecord = null; 264 } 265 resultWho = sourceRecord.resultWho; 266 requestCode = sourceRecord.requestCode; 267 sourceRecord.resultTo = null; 268 if (resultRecord != null) { 269 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode); 270 } 271 if (sourceRecord.launchedFromUid == callingUid) { 272 // The new activity is being launched from the same uid as the previous 273 // activity in the flow, and asking to forward its result back to the 274 // previous. In this case the activity is serving as a trampoline between 275 // the two, so we also want to update its launchedFromPackage to be the 276 // same as the previous activity. Note that this is safe, since we know 277 // these two packages come from the same uid; the caller could just as 278 // well have supplied that same package name itself. This specifially 279 // deals with the case of an intent picker/chooser being launched in the app 280 // flow to redirect to an activity picked by the user, where we want the final 281 // activity to consider it to have been launched by the previous app activity. 282 callingPackage = sourceRecord.launchedFromPackage; 283 } 284 } 285 286 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { 287 // We couldn't find a class that can handle the given Intent. 288 // That's the end of that! 289 err = ActivityManager.START_INTENT_NOT_RESOLVED; 290 } 291 292 if (err == ActivityManager.START_SUCCESS && aInfo == null) { 293 // We couldn't find the specific class specified in the Intent. 294 // Also the end of the line. 295 err = ActivityManager.START_CLASS_NOT_FOUND; 296 } 297 298 if (err == ActivityManager.START_SUCCESS && sourceRecord != null 299 && sourceRecord.task.voiceSession != null) { 300 // If this activity is being launched as part of a voice session, we need 301 // to ensure that it is safe to do so. If the upcoming activity will also 302 // be part of the voice session, we can only launch it if it has explicitly 303 // said it supports the VOICE category, or it is a part of the calling app. 304 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 305 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { 306 try { 307 intent.addCategory(Intent.CATEGORY_VOICE); 308 if (!AppGlobals.getPackageManager().activitySupportsIntent( 309 intent.getComponent(), intent, resolvedType)) { 310 Slog.w(TAG, 311 "Activity being started in current voice task does not support voice: " 312 + intent); 313 err = ActivityManager.START_NOT_VOICE_COMPATIBLE; 314 } 315 } catch (RemoteException e) { 316 Slog.w(TAG, "Failure checking voice capabilities", e); 317 err = ActivityManager.START_NOT_VOICE_COMPATIBLE; 318 } 319 } 320 } 321 322 if (err == ActivityManager.START_SUCCESS && voiceSession != null) { 323 // If the caller is starting a new voice session, just make sure the target 324 // is actually allowing it to run this way. 325 try { 326 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(), 327 intent, resolvedType)) { 328 Slog.w(TAG, 329 "Activity being started in new voice task does not support: " 330 + intent); 331 err = ActivityManager.START_NOT_VOICE_COMPATIBLE; 332 } 333 } catch (RemoteException e) { 334 Slog.w(TAG, "Failure checking voice capabilities", e); 335 err = ActivityManager.START_NOT_VOICE_COMPATIBLE; 336 } 337 } 338 339 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack; 340 341 if (err != START_SUCCESS) { 342 if (resultRecord != null) { 343 resultStack.sendActivityResultLocked( 344 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null); 345 } 346 ActivityOptions.abort(options); 347 return err; 348 } 349 350 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho, 351 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp, 352 resultRecord, resultStack); 353 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, 354 callingPid, resolvedType, aInfo.applicationInfo); 355 356 if (mService.mController != null) { 357 try { 358 // The Intent we give to the watcher has the extra data 359 // stripped off, since it can contain private information. 360 Intent watchIntent = intent.cloneFilter(); 361 abort |= !mService.mController.activityStarting(watchIntent, 362 aInfo.applicationInfo.packageName); 363 } catch (RemoteException e) { 364 mService.mController = null; 365 } 366 } 367 368 final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(intent, 369 resolvedType, aInfo, callingPackage, userId); 370 if (interceptingIntent != null) { 371 intent = interceptingIntent; 372 callingPid = realCallingPid; 373 callingUid = realCallingUid; 374 resolvedType = null; 375 // If we are intercepting and there was a task, convert it into an extra for the 376 // ConfirmCredentials intent and unassign it, as otherwise the task will move to 377 // front even if ConfirmCredentials is cancelled. 378 if (inTask != null) { 379 intent.putExtra(EXTRA_TASK_ID, inTask.taskId); 380 inTask = null; 381 } 382 383 final UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId); 384 rInfo = mSupervisor.resolveIntent(intent, resolvedType, parent.id); 385 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, 386 null /*profilerInfo*/); 387 } 388 389 if (abort) { 390 if (resultRecord != null) { 391 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, 392 RESULT_CANCELED, null); 393 } 394 // We pretend to the caller that it was really started, but 395 // they will just get a cancel result. 396 ActivityOptions.abort(options); 397 return START_SUCCESS; 398 } 399 400 // If permissions need a review before any of the app components can run, we 401 // launch the review activity and pass a pending intent to start the activity 402 // we are to launching now after the review is completed. 403 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) { 404 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired( 405 aInfo.packageName, userId)) { 406 IIntentSender target = mService.getIntentSenderLocked( 407 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, 408 callingUid, userId, null, null, 0, new Intent[]{intent}, 409 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT 410 | PendingIntent.FLAG_ONE_SHOT, null); 411 412 final int flags = intent.getFlags(); 413 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); 414 newIntent.setFlags(flags 415 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 416 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName); 417 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); 418 if (resultRecord != null) { 419 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true); 420 } 421 intent = newIntent; 422 423 resolvedType = null; 424 callingUid = realCallingUid; 425 callingPid = realCallingPid; 426 427 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); 428 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, 429 null /*profilerInfo*/); 430 431 if (DEBUG_PERMISSIONS_REVIEW) { 432 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, 433 true, false) + "} from uid " + callingUid + " on display " 434 + (container == null ? (mSupervisor.mFocusedStack == null ? 435 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) : 436 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY : 437 container.mActivityDisplay.mDisplayId))); 438 } 439 } 440 } 441 442 // If we have an ephemeral app, abort the process of launching the resolved intent. 443 // Instead, launch the ephemeral installer. Once the installer is finished, it 444 // starts either the intent we resolved here [on install error] or the ephemeral 445 // app [on install success]. 446 if (rInfo != null && rInfo.ephemeralResolveInfo != null) { 447 // Create a pending intent to start the intent resolved here. 448 final IIntentSender failureTarget = mService.getIntentSenderLocked( 449 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, 450 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent }, 451 new String[]{ resolvedType }, 452 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT 453 | PendingIntent.FLAG_IMMUTABLE, null); 454 455 // Create a pending intent to start the ephemeral application; force it to be 456 // directed to the ephemeral package. 457 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName()); 458 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked( 459 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, 460 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent }, 461 new String[]{ resolvedType }, 462 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT 463 | PendingIntent.FLAG_IMMUTABLE, null); 464 465 int flags = intent.getFlags(); 466 intent = new Intent(); 467 intent.setFlags(flags 468 | Intent.FLAG_ACTIVITY_NEW_TASK 469 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 470 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, 471 rInfo.ephemeralResolveInfo.getPackageName()); 472 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget)); 473 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget)); 474 475 resolvedType = null; 476 callingUid = realCallingUid; 477 callingPid = realCallingPid; 478 479 rInfo = rInfo.ephemeralInstaller; 480 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); 481 } 482 483 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, 484 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, 485 requestCode, componentSpecified, voiceSession != null, mSupervisor, container, 486 options); 487 if (outActivity != null) { 488 outActivity[0] = r; 489 } 490 491 if (r.appTimeTracker == null && sourceRecord != null) { 492 // If the caller didn't specify an explicit time tracker, we want to continue 493 // tracking under any it has. 494 r.appTimeTracker = sourceRecord.appTimeTracker; 495 } 496 497 final ActivityStack stack = mSupervisor.mFocusedStack; 498 if (voiceSession == null && (stack.mResumedActivity == null 499 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) { 500 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, 501 realCallingPid, realCallingUid, "Activity start")) { 502 PendingActivityLaunch pal = new PendingActivityLaunch(r, 503 sourceRecord, startFlags, stack, callerApp); 504 mPendingActivityLaunches.add(pal); 505 ActivityOptions.abort(options); 506 return ActivityManager.START_SWITCHES_CANCELED; 507 } 508 } 509 510 if (mService.mDidAppSwitch) { 511 // This is the second allowed switch since we stopped switches, 512 // so now just generally allow switches. Use case: user presses 513 // home (switches disabled, switch to home, mDidAppSwitch now true); 514 // user taps a home icon (coming from home so allowed, we hit here 515 // and now allow anyone to switch again). 516 mService.mAppSwitchesAllowedTime = 0; 517 } else { 518 mService.mDidAppSwitch = true; 519 } 520 521 doPendingActivityLaunchesLocked(false); 522 523 err = startActivityUnchecked( 524 r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask); 525 526 if (err < 0) { 527 // If someone asked to have the keyguard dismissed on the next 528 // activity start, but we are not actually doing an activity 529 // switch... just dismiss the keyguard now, because we 530 // probably want to see whatever is behind it. 531 mSupervisor.notifyActivityDrawnForKeyguard(); 532 } 533 return err; 534 } 535 536 /** 537 * Creates an intent to intercept the current activity start with Confirm Credentials if needed. 538 * 539 * @return The intercepting intent if needed. 540 */ 541 private Intent interceptWithConfirmCredentialsIfNeeded(Intent intent, String resolvedType, 542 ActivityInfo aInfo, String callingPackage, int userId) { 543 if (!mService.mUserController.shouldConfirmCredentials(userId)) { 544 return null; 545 } 546 final IIntentSender target = mService.getIntentSenderLocked( 547 INTENT_SENDER_ACTIVITY, callingPackage, 548 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent }, 549 new String[]{ resolvedType }, 550 FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE, null); 551 final int flags = intent.getFlags(); 552 final KeyguardManager km = (KeyguardManager) mService.mContext 553 .getSystemService(KEYGUARD_SERVICE); 554 final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId); 555 if (newIntent == null) { 556 return null; 557 } 558 newIntent.setFlags(flags | FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 559 newIntent.putExtra(EXTRA_PACKAGE_NAME, aInfo.packageName); 560 newIntent.putExtra(EXTRA_INTENT, new IntentSender(target)); 561 return newIntent; 562 } 563 564 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) { 565 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason); 566 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/, 567 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/, 568 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/, 569 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/, 570 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/, 571 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/, 572 null /*container*/, null /*inTask*/); 573 if (mSupervisor.inResumeTopActivity) { 574 // If we are in resume section already, home activity will be initialized, but not 575 // resumed (to avoid recursive resume) and will stay that way until something pokes it 576 // again. We need to schedule another resume. 577 mSupervisor.scheduleResumeTopActivities(); 578 } 579 } 580 581 final int startActivityMayWait(IApplicationThread caller, int callingUid, 582 String callingPackage, Intent intent, String resolvedType, 583 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 584 IBinder resultTo, String resultWho, int requestCode, int startFlags, 585 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config, 586 Bundle bOptions, boolean ignoreTargetSecurity, int userId, 587 IActivityContainer iContainer, TaskRecord inTask) { 588 // Refuse possible leaked file descriptors 589 if (intent != null && intent.hasFileDescriptors()) { 590 throw new IllegalArgumentException("File descriptors passed in Intent"); 591 } 592 boolean componentSpecified = intent.getComponent() != null; 593 594 // Save a copy in case ephemeral needs it 595 final Intent ephemeralIntent = new Intent(intent); 596 // Don't modify the client's object! 597 intent = new Intent(intent); 598 599 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); 600 // Collect information about the target of the Intent. 601 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); 602 603 ActivityOptions options = ActivityOptions.fromBundle(bOptions); 604 ActivityStackSupervisor.ActivityContainer container = 605 (ActivityStackSupervisor.ActivityContainer)iContainer; 606 synchronized (mService) { 607 if (container != null && container.mParentActivity != null && 608 container.mParentActivity.state != RESUMED) { 609 // Cannot start a child activity if the parent is not resumed. 610 return ActivityManager.START_CANCELED; 611 } 612 final int realCallingPid = Binder.getCallingPid(); 613 final int realCallingUid = Binder.getCallingUid(); 614 int callingPid; 615 if (callingUid >= 0) { 616 callingPid = -1; 617 } else if (caller == null) { 618 callingPid = realCallingPid; 619 callingUid = realCallingUid; 620 } else { 621 callingPid = callingUid = -1; 622 } 623 624 final ActivityStack stack; 625 if (container == null || container.mStack.isOnHomeDisplay()) { 626 stack = mSupervisor.mFocusedStack; 627 } else { 628 stack = container.mStack; 629 } 630 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; 631 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 632 "Starting activity when config will change = " + stack.mConfigWillChange); 633 634 final long origId = Binder.clearCallingIdentity(); 635 636 if (aInfo != null && 637 (aInfo.applicationInfo.privateFlags 638 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { 639 // This may be a heavy-weight process! Check to see if we already 640 // have another, different heavy-weight process running. 641 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { 642 final ProcessRecord heavy = mService.mHeavyWeightProcess; 643 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid 644 || !heavy.processName.equals(aInfo.processName))) { 645 int appCallingUid = callingUid; 646 if (caller != null) { 647 ProcessRecord callerApp = mService.getRecordForAppLocked(caller); 648 if (callerApp != null) { 649 appCallingUid = callerApp.info.uid; 650 } else { 651 Slog.w(TAG, "Unable to find app for caller " + caller 652 + " (pid=" + callingPid + ") when starting: " 653 + intent.toString()); 654 ActivityOptions.abort(options); 655 return ActivityManager.START_PERMISSION_DENIED; 656 } 657 } 658 659 IIntentSender target = mService.getIntentSenderLocked( 660 ActivityManager.INTENT_SENDER_ACTIVITY, "android", 661 appCallingUid, userId, null, null, 0, new Intent[] { intent }, 662 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT 663 | PendingIntent.FLAG_ONE_SHOT, null); 664 665 Intent newIntent = new Intent(); 666 if (requestCode >= 0) { 667 // Caller is requesting a result. 668 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); 669 } 670 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, 671 new IntentSender(target)); 672 if (heavy.activities.size() > 0) { 673 ActivityRecord hist = heavy.activities.get(0); 674 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, 675 hist.packageName); 676 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, 677 hist.task.taskId); 678 } 679 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, 680 aInfo.packageName); 681 newIntent.setFlags(intent.getFlags()); 682 newIntent.setClassName("android", 683 HeavyWeightSwitcherActivity.class.getName()); 684 intent = newIntent; 685 resolvedType = null; 686 caller = null; 687 callingUid = Binder.getCallingUid(); 688 callingPid = Binder.getCallingPid(); 689 componentSpecified = true; 690 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId); 691 aInfo = rInfo != null ? rInfo.activityInfo : null; 692 if (aInfo != null) { 693 aInfo = mService.getActivityInfoForUser(aInfo, userId); 694 } 695 } 696 } 697 } 698 699 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, 700 aInfo, rInfo, voiceSession, voiceInteractor, 701 resultTo, resultWho, requestCode, callingPid, 702 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, 703 options, ignoreTargetSecurity, componentSpecified, null, container, inTask); 704 705 Binder.restoreCallingIdentity(origId); 706 707 if (stack.mConfigWillChange) { 708 // If the caller also wants to switch to a new configuration, 709 // do so now. This allows a clean switch, as we are waiting 710 // for the current activity to pause (so we will not destroy 711 // it), and have not yet started the next activity. 712 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, 713 "updateConfiguration()"); 714 stack.mConfigWillChange = false; 715 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 716 "Updating to new configuration after starting activity."); 717 mService.updateConfigurationLocked(config, null, false); 718 } 719 720 if (outResult != null) { 721 outResult.result = res; 722 if (res == ActivityManager.START_SUCCESS) { 723 mSupervisor.mWaitingActivityLaunched.add(outResult); 724 do { 725 try { 726 mService.wait(); 727 } catch (InterruptedException e) { 728 } 729 } while (!outResult.timeout && outResult.who == null); 730 } else if (res == START_TASK_TO_FRONT) { 731 ActivityRecord r = stack.topRunningActivityLocked(); 732 if (r.nowVisible && r.state == RESUMED) { 733 outResult.timeout = false; 734 outResult.who = new ComponentName(r.info.packageName, r.info.name); 735 outResult.totalTime = 0; 736 outResult.thisTime = 0; 737 } else { 738 outResult.thisTime = SystemClock.uptimeMillis(); 739 mSupervisor.mWaitingActivityVisible.add(outResult); 740 do { 741 try { 742 mService.wait(); 743 } catch (InterruptedException e) { 744 } 745 } while (!outResult.timeout && outResult.who == null); 746 } 747 } 748 } 749 750 return res; 751 } 752 } 753 754 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage, 755 Intent[] intents, String[] resolvedTypes, IBinder resultTo, 756 Bundle bOptions, int userId) { 757 if (intents == null) { 758 throw new NullPointerException("intents is null"); 759 } 760 if (resolvedTypes == null) { 761 throw new NullPointerException("resolvedTypes is null"); 762 } 763 if (intents.length != resolvedTypes.length) { 764 throw new IllegalArgumentException("intents are length different than resolvedTypes"); 765 } 766 767 768 int callingPid; 769 if (callingUid >= 0) { 770 callingPid = -1; 771 } else if (caller == null) { 772 callingPid = Binder.getCallingPid(); 773 callingUid = Binder.getCallingUid(); 774 } else { 775 callingPid = callingUid = -1; 776 } 777 final long origId = Binder.clearCallingIdentity(); 778 try { 779 synchronized (mService) { 780 ActivityRecord[] outActivity = new ActivityRecord[1]; 781 for (int i=0; i<intents.length; i++) { 782 Intent intent = intents[i]; 783 if (intent == null) { 784 continue; 785 } 786 787 // Refuse possible leaked file descriptors 788 if (intent != null && intent.hasFileDescriptors()) { 789 throw new IllegalArgumentException("File descriptors passed in Intent"); 790 } 791 792 boolean componentSpecified = intent.getComponent() != null; 793 794 // Don't modify the client's object! 795 intent = new Intent(intent); 796 797 // Collect information about the target of the Intent. 798 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0, 799 null, userId); 800 // TODO: New, check if this is correct 801 aInfo = mService.getActivityInfoForUser(aInfo, userId); 802 803 if (aInfo != null && 804 (aInfo.applicationInfo.privateFlags 805 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { 806 throw new IllegalArgumentException( 807 "FLAG_CANT_SAVE_STATE not supported here"); 808 } 809 810 ActivityOptions options = ActivityOptions.fromBundle( 811 i == intents.length - 1 ? bOptions : null); 812 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/, 813 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1, 814 callingPid, callingUid, callingPackage, callingPid, callingUid, 0, 815 options, false, componentSpecified, outActivity, null, null); 816 if (res < 0) { 817 return res; 818 } 819 820 resultTo = outActivity[0] != null ? outActivity[0].appToken : null; 821 } 822 } 823 } finally { 824 Binder.restoreCallingIdentity(origId); 825 } 826 827 return START_SUCCESS; 828 } 829 830 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, 831 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 832 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) { 833 834 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, 835 voiceInteractor); 836 837 computeLaunchingTaskFlags(); 838 839 computeSourceStack(); 840 841 mIntent.setFlags(mLaunchFlags); 842 843 ActivityRecord intentActivity = getReusableIntentActivity(); 844 845 if (intentActivity != null) { 846 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but 847 // still needs to be a lock task mode violation since the task gets cleared out and 848 // the device would otherwise leave the locked task. 849 if (mSupervisor.isLockTaskModeViolation(intentActivity.task, 850 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) 851 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { 852 mSupervisor.showLockTaskToast(); 853 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); 854 return START_RETURN_LOCK_TASK_MODE_VIOLATION; 855 } 856 857 if (mStartActivity.task == null) { 858 mStartActivity.task = intentActivity.task; 859 } 860 if (intentActivity.task.intent == null) { 861 // This task was started because of movement of the activity based on affinity... 862 // Now that we are actually launching it, we can assign the base intent. 863 intentActivity.task.setIntent(mStartActivity); 864 } 865 866 intentActivity = setTargetStackAndMoveToFrontIfNeeded(intentActivity); 867 868 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { 869 // We don't need to start a new activity, and the client said not to do anything 870 // if that is the case, so this is it! And for paranoia, make sure we have 871 // correctly resumed the top activity. 872 resumeTargetStackIfNeeded(); 873 return START_RETURN_INTENT_TO_CALLER; 874 } 875 876 setTaskFromIntentActivity(intentActivity); 877 878 if (!mAddingToTask && mReuseTask == null) { 879 // We didn't do anything... but it was needed (a.k.a., client don't use that 880 // intent!) And for paranoia, make sure we have correctly resumed the top activity. 881 resumeTargetStackIfNeeded(); 882 return START_TASK_TO_FRONT; 883 } 884 } 885 886 if (mStartActivity.packageName == null) { 887 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) { 888 mStartActivity.resultTo.task.stack.sendActivityResultLocked( 889 -1, mStartActivity.resultTo, mStartActivity.resultWho, 890 mStartActivity.requestCode, RESULT_CANCELED, null); 891 } 892 ActivityOptions.abort(mOptions); 893 return START_CLASS_NOT_FOUND; 894 } 895 896 // If the activity being launched is the same as the one currently at the top, then 897 // we need to check if it should only be launched once. 898 final ActivityStack topStack = mSupervisor.mFocusedStack; 899 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); 900 final boolean dontStart = top != null && mStartActivity.resultTo == null 901 && top.realActivity.equals(mStartActivity.realActivity) 902 && top.userId == mStartActivity.userId 903 && top.app != null && top.app.thread != null 904 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 905 || mLaunchSingleTop || mLaunchSingleTask); 906 if (dontStart) { 907 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); 908 // For paranoia, make sure we have correctly resumed the top activity. 909 topStack.mLastPausedActivity = null; 910 if (mDoResume) { 911 mSupervisor.resumeFocusedStackTopActivityLocked(); 912 } 913 ActivityOptions.abort(mOptions); 914 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { 915 // We don't need to start a new activity, and the client said not to do 916 // anything if that is the case, so this is it! 917 return START_RETURN_INTENT_TO_CALLER; 918 } 919 top.deliverNewIntentLocked( 920 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); 921 return START_DELIVERED_TO_TOP; 922 } 923 924 boolean newTask = false; 925 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) 926 ? mSourceRecord.task : null; 927 928 // Should this be considered a new task? 929 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask 930 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { 931 newTask = true; 932 setTaskFromReuseOrCreateNewTask(taskToAffiliate); 933 934 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) { 935 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); 936 return START_RETURN_LOCK_TASK_MODE_VIOLATION; 937 } 938 if (!mMovedHome 939 && (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) 940 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { 941 // Caller wants to appear on home activity, so before starting 942 // their own activity we will bring home to the front. 943 mStartActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); 944 } 945 } else if (mSourceRecord != null) { 946 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) { 947 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); 948 return START_RETURN_LOCK_TASK_MODE_VIOLATION; 949 } 950 951 final int result = setTaskFromSourceRecord(); 952 if (result != START_SUCCESS) { 953 return result; 954 } 955 } else if (mInTask != null) { 956 // The caller is asking that the new activity be started in an explicit 957 // task it has provided to us. 958 if (mSupervisor.isLockTaskModeViolation(mInTask)) { 959 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); 960 return START_RETURN_LOCK_TASK_MODE_VIOLATION; 961 } 962 963 final int result = setTaskFromInTask(); 964 if (result != START_SUCCESS) { 965 return result; 966 } 967 } else { 968 // This not being started from an existing activity, and not part of a new task... 969 // just put it in the top task, though these days this case should never happen. 970 setTaskToCurrentTopOrCreateNewTask(); 971 } 972 973 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName, 974 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId); 975 976 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) { 977 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE); 978 } 979 if (newTask) { 980 EventLog.writeEvent( 981 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId); 982 } 983 ActivityStack.logStartActivity( 984 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task); 985 mTargetStack.mLastPausedActivity = null; 986 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions); 987 if (mDoResume) { 988 if (!mLaunchTaskBehind) { 989 // TODO(b/26381750): Remove this code after verification that all the decision 990 // points above moved targetStack to the front which will also set the focus 991 // activity. 992 mService.setFocusedActivityLocked(mStartActivity, "startedActivity"); 993 } 994 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, 995 mOptions); 996 } else { 997 mTargetStack.addRecentActivityLocked(mStartActivity); 998 } 999 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); 1000 1001 if (!mStartActivity.task.mResizeable 1002 && mSupervisor.isStackDockedInEffect(mTargetStack.mStackId)) { 1003 mSupervisor.showNonResizeableDockToast(mStartActivity.task.taskId); 1004 } 1005 1006 return START_SUCCESS; 1007 } 1008 1009 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask, 1010 boolean doResume, int startFlags, ActivityRecord sourceRecord, 1011 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) { 1012 reset(); 1013 1014 mStartActivity = r; 1015 mIntent = r.intent; 1016 mOptions = options; 1017 mCallingUid = r.launchedFromUid; 1018 mSourceRecord = sourceRecord; 1019 mVoiceSession = voiceSession; 1020 mVoiceInteractor = voiceInteractor; 1021 1022 mLaunchBounds = getOverrideBounds(r, options, inTask); 1023 1024 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP; 1025 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE; 1026 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK; 1027 mLaunchFlags = adjustLaunchFlagsToDocumentMode( 1028 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags()); 1029 mLaunchTaskBehind = r.mLaunchTaskBehind 1030 && !mLaunchSingleTask && !mLaunchSingleInstance 1031 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0; 1032 1033 sendNewTaskResultRequestIfNeeded(); 1034 1035 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { 1036 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; 1037 } 1038 1039 // If we are actually going to launch in to a new task, there are some cases where 1040 // we further want to do multiple task. 1041 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { 1042 if (mLaunchTaskBehind 1043 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) { 1044 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK; 1045 } 1046 } 1047 1048 // We'll invoke onUserLeaving before onPause only if the launching 1049 // activity did not explicitly state that this is an automated launch. 1050 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0; 1051 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 1052 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving); 1053 1054 // If the caller has asked not to resume at this point, we make note 1055 // of this in the record so that we can skip it when trying to find 1056 // the top running activity. 1057 mDoResume = doResume; 1058 if (!doResume || !mSupervisor.okToShowLocked(r)) { 1059 r.delayedResume = true; 1060 mDoResume = false; 1061 } 1062 1063 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; 1064 1065 mInTask = inTask; 1066 // In some flows in to this function, we retrieve the task record and hold on to it 1067 // without a lock before calling back in to here... so the task at this point may 1068 // not actually be in recents. Check for that, and if it isn't in recents just 1069 // consider it invalid. 1070 if (inTask != null && !inTask.inRecents) { 1071 Slog.w(TAG, "Starting activity in task not in recents: " + inTask); 1072 mInTask = null; 1073 } 1074 1075 mStartFlags = startFlags; 1076 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched 1077 // is the same as the one making the call... or, as a special case, if we do not know 1078 // the caller then we count the current top activity as the caller. 1079 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { 1080 ActivityRecord checkedCaller = sourceRecord; 1081 if (checkedCaller == null) { 1082 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked( 1083 mNotTop); 1084 } 1085 if (!checkedCaller.realActivity.equals(r.realActivity)) { 1086 // Caller is not the same as launcher, so always needed. 1087 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED; 1088 } 1089 } 1090 1091 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0; 1092 } 1093 1094 private void sendNewTaskResultRequestIfNeeded() { 1095 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 1096 && mStartActivity.resultTo.task.stack != null) { 1097 // For whatever reason this activity is being launched into a new task... 1098 // yet the caller has requested a result back. Well, that is pretty messed up, 1099 // so instead immediately send back a cancel and let the new task continue launched 1100 // as normal without a dependency on its originator. 1101 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result."); 1102 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo, 1103 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null); 1104 mStartActivity.resultTo = null; 1105 } 1106 } 1107 1108 private void computeLaunchingTaskFlags() { 1109 // If the caller is not coming from another activity, but has given us an explicit task into 1110 // which they would like us to launch the new activity, then let's see about doing that. 1111 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) { 1112 final Intent baseIntent = mInTask.getBaseIntent(); 1113 final ActivityRecord root = mInTask.getRootActivity(); 1114 if (baseIntent == null) { 1115 ActivityOptions.abort(mOptions); 1116 throw new IllegalArgumentException("Launching into task without base intent: " 1117 + mInTask); 1118 } 1119 1120 // If this task is empty, then we are adding the first activity -- it 1121 // determines the root, and must be launching as a NEW_TASK. 1122 if (mLaunchSingleInstance || mLaunchSingleTask) { 1123 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) { 1124 ActivityOptions.abort(mOptions); 1125 throw new IllegalArgumentException("Trying to launch singleInstance/Task " 1126 + mStartActivity + " into different task " + mInTask); 1127 } 1128 if (root != null) { 1129 ActivityOptions.abort(mOptions); 1130 throw new IllegalArgumentException("Caller with mInTask " + mInTask 1131 + " has root " + root + " but target is singleInstance/Task"); 1132 } 1133 } 1134 1135 // If task is empty, then adopt the interesting intent launch flags in to the 1136 // activity being started. 1137 if (root == null) { 1138 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK 1139 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS; 1140 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest) 1141 | (baseIntent.getFlags() & flagsOfInterest); 1142 mIntent.setFlags(mLaunchFlags); 1143 mInTask.setIntent(mStartActivity); 1144 mAddingToTask = true; 1145 1146 // If the task is not empty and the caller is asking to start it as the root of 1147 // a new task, then we don't actually want to start this on the task. We will 1148 // bring the task to the front, and possibly give it a new intent. 1149 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { 1150 mAddingToTask = false; 1151 1152 } else { 1153 mAddingToTask = true; 1154 } 1155 1156 mReuseTask = mInTask; 1157 } else { 1158 mInTask = null; 1159 // Launch ResolverActivity in the source task, so that it stays in the task bounds 1160 // when in freeform workspace. 1161 // Also put noDisplay activities in the source task. These by itself can be placed 1162 // in any task/stack, however it could launch other activities like ResolverActivity, 1163 // and we want those to stay in the original task. 1164 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null 1165 && mSourceRecord.isFreeform()) { 1166 mAddingToTask = true; 1167 } 1168 } 1169 1170 if (mInTask == null) { 1171 if (mSourceRecord == null) { 1172 // This activity is not being started from another... in this 1173 // case we -always- start a new task. 1174 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) { 1175 Slog.w(TAG, "startActivity called from non-Activity context; forcing " + 1176 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent); 1177 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; 1178 } 1179 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) { 1180 // The original activity who is starting us is running as a single 1181 // instance... this new activity it is starting must go on its 1182 // own task. 1183 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; 1184 } else if (mLaunchSingleInstance || mLaunchSingleTask) { 1185 // The activity being started is a single instance... it always 1186 // gets launched into its own task. 1187 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; 1188 } 1189 } 1190 } 1191 1192 private void computeSourceStack() { 1193 if (mSourceRecord == null) { 1194 mSourceStack = null; 1195 return; 1196 } 1197 if (!mSourceRecord.finishing) { 1198 mSourceStack = mSourceRecord.task.stack; 1199 return; 1200 } 1201 1202 // If the source is finishing, we can't further count it as our source. This is because the 1203 // task it is associated with may now be empty and on its way out, so we don't want to 1204 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find 1205 // a task for it. But save the task information so it can be used when creating the new task. 1206 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) { 1207 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord 1208 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent); 1209 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; 1210 mNewTaskInfo = mSourceRecord.info; 1211 mNewTaskIntent = mSourceRecord.task.intent; 1212 } 1213 mSourceRecord = null; 1214 mSourceStack = null; 1215 } 1216 1217 /** 1218 * Decide whether the new activity should be inserted into an existing task. Returns null 1219 * if not or an ActivityRecord with the task into which the new activity should be added. 1220 */ 1221 private ActivityRecord getReusableIntentActivity() { 1222 // We may want to try to place the new activity in to an existing task. We always 1223 // do this if the target activity is singleTask or singleInstance; we will also do 1224 // this if NEW_TASK has been requested, and there is not an additional qualifier telling 1225 // us to still place it in a new task: multi task, always doc mode, or being asked to 1226 // launch this as a new task behind the current one. 1227 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 && 1228 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0) 1229 || mLaunchSingleInstance || mLaunchSingleTask; 1230 // If bring to front is requested, and no result is requested and we have not been given 1231 // an explicit task to launch in to, and we can find a task that was started with this 1232 // same component, then instead of launching bring that one to the front. 1233 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null; 1234 ActivityRecord intentActivity = null; 1235 if (putIntoExistingTask) { 1236 // See if there is a task to bring to the front. If this is a SINGLE_INSTANCE 1237 // activity, there can be one and only one instance of it in the history, and it is 1238 // always in its own unique task, so we do a special search. 1239 intentActivity = mLaunchSingleInstance ? mSupervisor.findActivityLocked(mIntent, mStartActivity.info) 1240 : mSupervisor.findTaskLocked(mStartActivity); 1241 } 1242 return intentActivity; 1243 } 1244 1245 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) { 1246 mTargetStack = intentActivity.task.stack; 1247 mTargetStack.mLastPausedActivity = null; 1248 // If the target task is not in the front, then we need to bring it to the front... 1249 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have 1250 // the same behavior as if a new instance was being started, which means not bringing it 1251 // to the front if the caller is not itself in the front. 1252 final ActivityStack focusStack = mSupervisor.getFocusedStack(); 1253 ActivityRecord curTop = (focusStack == null) 1254 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop); 1255 1256 if (curTop != null && (curTop.task != intentActivity.task || 1257 curTop.task != focusStack.topTask())) { 1258 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 1259 if (mSourceRecord == null || (mSourceStack.topActivity() != null && 1260 mSourceStack.topActivity().task == mSourceRecord.task)) { 1261 // We really do want to push this one into the user's face, right now. 1262 if (mLaunchTaskBehind && mSourceRecord != null) { 1263 intentActivity.setTaskToAffiliateWith(mSourceRecord.task); 1264 } 1265 mMovedHome = true; 1266 final ActivityStack launchStack = 1267 getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task, 1268 mOptions, true); 1269 if (launchStack == null || launchStack == mTargetStack) { 1270 // We only want to move to the front, if we aren't going to launch on a 1271 // different stack. If we launch on a different stack, we will put the 1272 // task on top there. 1273 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation, 1274 mOptions, mStartActivity.appTimeTracker, "bringingFoundTaskToFront"); 1275 mMovedToFront = true; 1276 } 1277 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) 1278 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { 1279 // Caller wants to appear on home activity. 1280 intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); 1281 } 1282 mOptions = null; 1283 } 1284 } 1285 if (!mMovedToFront && mDoResume) { 1286 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack 1287 + " from " + intentActivity); 1288 mTargetStack.moveToFront("intentActivityFound"); 1289 } 1290 1291 // If the caller has requested that the target task be reset, then do so. 1292 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 1293 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity); 1294 } 1295 return intentActivity; 1296 } 1297 1298 private void setTaskFromIntentActivity(ActivityRecord intentActivity) { 1299 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) 1300 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) { 1301 // The caller has requested to completely replace any existing task with its new 1302 // activity. Well that should not be too hard... 1303 mReuseTask = intentActivity.task; 1304 mReuseTask.performClearTaskLocked(); 1305 mReuseTask.setIntent(mStartActivity); 1306 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 1307 || mLaunchSingleInstance || mLaunchSingleTask) { 1308 // In this situation we want to remove all activities from the task up to the one 1309 // being started. In most cases this means we are resetting the task to its initial 1310 // state. 1311 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity, 1312 mLaunchFlags); 1313 if (top != null) { 1314 if (top.frontOfTask) { 1315 // Activity aliases may mean we use different intents for the top activity, 1316 // so make sure the task now has the identity of the new intent. 1317 top.task.setIntent(mStartActivity); 1318 } 1319 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity, top.task); 1320 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); 1321 } else { 1322 // A special case: we need to start the activity because it is not currently 1323 // running, and the caller has asked to clear the current task to have this 1324 // activity at the top. 1325 mAddingToTask = true; 1326 // Now pretend like this activity is being started by the top of its task, so it 1327 // is put in the right place. 1328 mSourceRecord = intentActivity; 1329 final TaskRecord task = mSourceRecord.task; 1330 if (task != null && task.stack == null) { 1331 // Target stack got cleared when we all activities were removed above. 1332 // Go ahead and reset it. 1333 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */, 1334 null /* bounds */, mLaunchFlags, mOptions); 1335 mTargetStack.addTask(task, 1336 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked"); 1337 } 1338 } 1339 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) { 1340 // In this case the top activity on the task is the same as the one being launched, 1341 // so we take that as a request to bring the task to the foreground. If the top 1342 // activity in the task is the root activity, deliver this new intent to it if it 1343 // desires. 1344 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop) 1345 && intentActivity.realActivity.equals(mStartActivity.realActivity)) { 1346 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity, 1347 intentActivity.task); 1348 if (intentActivity.frontOfTask) { 1349 intentActivity.task.setIntent(mStartActivity); 1350 } 1351 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, 1352 mStartActivity.launchedFromPackage); 1353 } else if (!mStartActivity.intent.filterEquals(intentActivity.task.intent)) { 1354 // In this case we are launching the root activity of the task, but with a 1355 // different intent. We should start a new instance on top. 1356 mAddingToTask = true; 1357 mSourceRecord = intentActivity; 1358 } 1359 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { 1360 // In this case an activity is being launched in to an existing task, without 1361 // resetting that task. This is typically the situation of launching an activity 1362 // from a notification or shortcut. We want to place the new activity on top of the 1363 // current task. 1364 mAddingToTask = true; 1365 mSourceRecord = intentActivity; 1366 } else if (!intentActivity.task.rootWasReset) { 1367 // In this case we are launching into an existing task that has not yet been started 1368 // from its front door. The current task has been brought to the front. Ideally, 1369 // we'd probably like to place this new task at the bottom of its stack, but that's 1370 // a little hard to do with the current organization of the code so for now we'll 1371 // just drop it. 1372 intentActivity.task.setIntent(mStartActivity); 1373 } 1374 } 1375 1376 private void resumeTargetStackIfNeeded() { 1377 if (mDoResume) { 1378 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions); 1379 if (!mMovedToFront) { 1380 // Make sure to notify Keyguard as well if we are not running an app transition 1381 // later. 1382 mSupervisor.notifyActivityDrawnForKeyguard(); 1383 } 1384 } else { 1385 ActivityOptions.abort(mOptions); 1386 } 1387 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); 1388 } 1389 1390 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) { 1391 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags, 1392 mOptions); 1393 if (mDoResume) { 1394 mTargetStack.moveToFront("startingNewTask"); 1395 } 1396 1397 if (mReuseTask == null) { 1398 final TaskRecord task = mTargetStack.createTaskRecord(mSupervisor.getNextTaskId(), 1399 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info, 1400 mNewTaskIntent != null ? mNewTaskIntent : mIntent, 1401 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */); 1402 mStartActivity.setTask(task, taskToAffiliate); 1403 if (mLaunchBounds != null) { 1404 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds); 1405 } 1406 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 1407 "Starting new activity " + 1408 mStartActivity + " in new task " + mStartActivity.task); 1409 } else { 1410 mStartActivity.setTask(mReuseTask, taskToAffiliate); 1411 } 1412 } 1413 1414 private int setTaskFromSourceRecord() { 1415 final TaskRecord sourceTask = mSourceRecord.task; 1416 // We only want to allow changing stack if the target task is not the top one, 1417 // otherwise we would move the launching task to the other side, rather than show 1418 // two side by side. 1419 final boolean launchToSideAllowed = sourceTask.stack.topTask() != sourceTask; 1420 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, launchToSideAllowed); 1421 1422 if (mTargetStack == null) { 1423 mTargetStack = sourceTask.stack; 1424 } else if (mTargetStack != sourceTask.stack) { 1425 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId, 1426 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE); 1427 } 1428 if (mDoResume) { 1429 mTargetStack.moveToFront("sourceStackToFront"); 1430 } 1431 final TaskRecord topTask = mTargetStack.topTask(); 1432 if (topTask != sourceTask) { 1433 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions, 1434 mStartActivity.appTimeTracker, "sourceTaskToFront"); 1435 } 1436 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) { 1437 // In this case, we are adding the activity to an existing task, but the caller has 1438 // asked to clear that task if the activity is already running. 1439 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags); 1440 mKeepCurTransition = true; 1441 if (top != null) { 1442 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity, top.task); 1443 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); 1444 // For paranoia, make sure we have correctly resumed the top activity. 1445 mTargetStack.mLastPausedActivity = null; 1446 if (mDoResume) { 1447 mSupervisor.resumeFocusedStackTopActivityLocked(); 1448 } 1449 ActivityOptions.abort(mOptions); 1450 return START_DELIVERED_TO_TOP; 1451 } 1452 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { 1453 // In this case, we are launching an activity in our own task that may already be 1454 // running somewhere in the history, and we want to shuffle it to the front of the 1455 // stack if so. 1456 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity); 1457 if (top != null) { 1458 final TaskRecord task = top.task; 1459 task.moveActivityToFrontLocked(top); 1460 top.updateOptionsLocked(mOptions); 1461 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity, task); 1462 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); 1463 mTargetStack.mLastPausedActivity = null; 1464 if (mDoResume) { 1465 mSupervisor.resumeFocusedStackTopActivityLocked(); 1466 } 1467 return START_DELIVERED_TO_TOP; 1468 } 1469 } 1470 1471 // An existing activity is starting this new activity, so we want to keep the new one in 1472 // the same task as the one that is starting it. 1473 mStartActivity.setTask(sourceTask, null); 1474 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity 1475 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord); 1476 return START_SUCCESS; 1477 } 1478 1479 private int setTaskFromInTask() { 1480 if (mLaunchBounds != null) { 1481 mInTask.updateOverrideConfiguration(mLaunchBounds); 1482 int stackId = mInTask.getLaunchStackId(); 1483 if (stackId != mInTask.stack.mStackId) { 1484 mSupervisor.moveTaskToStackUncheckedLocked( 1485 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront"); 1486 } 1487 } 1488 mTargetStack = mInTask.stack; 1489 mTargetStack.moveTaskToFrontLocked( 1490 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront"); 1491 1492 // Check whether we should actually launch the new activity in to the task, 1493 // or just reuse the current activity on top. 1494 ActivityRecord top = mInTask.getTopActivity(); 1495 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) { 1496 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 1497 || mLaunchSingleTop || mLaunchSingleTask) { 1498 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); 1499 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { 1500 // We don't need to start a new activity, and the client said not to do 1501 // anything if that is the case, so this is it! 1502 return START_RETURN_INTENT_TO_CALLER; 1503 } 1504 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); 1505 return START_DELIVERED_TO_TOP; 1506 } 1507 } 1508 1509 if (!mAddingToTask) { 1510 // We don't actually want to have this activity added to the task, so just 1511 // stop here but still tell the caller that we consumed the intent. 1512 ActivityOptions.abort(mOptions); 1513 return START_TASK_TO_FRONT; 1514 } 1515 1516 mStartActivity.setTask(mInTask, null); 1517 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 1518 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task); 1519 1520 return START_SUCCESS; 1521 } 1522 1523 private void setTaskToCurrentTopOrCreateNewTask() { 1524 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags, 1525 mOptions); 1526 if (mDoResume) { 1527 mTargetStack.moveToFront("addingToTopTask"); 1528 } 1529 final ActivityRecord prev = mTargetStack.topActivity(); 1530 final TaskRecord task = prev != null ? prev.task 1531 : mTargetStack.createTaskRecord( 1532 mSupervisor.getNextTaskId(), mStartActivity.info, mIntent, null, null, true); 1533 mStartActivity.setTask(task, null); 1534 mWindowManager.moveTaskToTop(mStartActivity.task.taskId); 1535 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 1536 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task); 1537 } 1538 1539 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance, 1540 boolean launchSingleTask, int launchFlags) { 1541 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && 1542 (launchSingleInstance || launchSingleTask)) { 1543 // We have a conflict between the Intent and the Activity manifest, manifest wins. 1544 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " + 1545 "\"singleInstance\" or \"singleTask\""); 1546 launchFlags &= 1547 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK); 1548 } else { 1549 switch (r.info.documentLaunchMode) { 1550 case ActivityInfo.DOCUMENT_LAUNCH_NONE: 1551 break; 1552 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING: 1553 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; 1554 break; 1555 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS: 1556 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; 1557 break; 1558 case ActivityInfo.DOCUMENT_LAUNCH_NEVER: 1559 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK; 1560 break; 1561 } 1562 } 1563 return launchFlags; 1564 } 1565 1566 final void doPendingActivityLaunchesLocked(boolean doResume) { 1567 while (!mPendingActivityLaunches.isEmpty()) { 1568 PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); 1569 1570 try { 1571 startActivityUnchecked(pal.r, pal.sourceRecord, null, null, pal.startFlags, 1572 doResume && mPendingActivityLaunches.isEmpty(), null, null); 1573 } catch (Exception e) { 1574 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e); 1575 pal.sendErrorResult(e.getMessage()); 1576 } 1577 } 1578 } 1579 1580 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds, 1581 int launchFlags, ActivityOptions aOptions) { 1582 final TaskRecord task = r.task; 1583 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) { 1584 return mSupervisor.mHomeStack; 1585 } 1586 1587 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions, true); 1588 if (stack != null) { 1589 return stack; 1590 } 1591 1592 if (task != null && task.stack != null) { 1593 stack = task.stack; 1594 if (stack.isOnHomeDisplay()) { 1595 if (mSupervisor.mFocusedStack != stack) { 1596 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, 1597 "computeStackFocus: Setting " + "focused stack to r=" + r 1598 + " task=" + task); 1599 } else { 1600 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, 1601 "computeStackFocus: Focused stack already=" 1602 + mSupervisor.mFocusedStack); 1603 } 1604 } 1605 return stack; 1606 } 1607 1608 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer; 1609 if (container != null) { 1610 // The first time put it on the desired stack, after this put on task stack. 1611 r.mInitialActivityContainer = null; 1612 return container.mStack; 1613 } 1614 1615 // The fullscreen stack can contain any task regardless of if the task is resizeable 1616 // or not. So, we let the task go in the fullscreen task if it is the focus stack. 1617 // If the freeform or docked stack has focus, and the activity to be launched is resizeable, 1618 // we can also put it in the focused stack. 1619 final int focusedStackId = mSupervisor.mFocusedStack.mStackId; 1620 final boolean canUseFocusedStack = 1621 focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID 1622 || focusedStackId == DOCKED_STACK_ID 1623 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeable()); 1624 if (canUseFocusedStack && (!newTask 1625 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) { 1626 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, 1627 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack); 1628 return mSupervisor.mFocusedStack; 1629 } 1630 1631 // We first try to put the task in the first dynamic stack. 1632 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks; 1633 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1634 stack = homeDisplayStacks.get(stackNdx); 1635 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) { 1636 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, 1637 "computeStackFocus: Setting focused stack=" + stack); 1638 return stack; 1639 } 1640 } 1641 1642 // If there is no suitable dynamic stack then we figure out which static stack to use. 1643 final int stackId = task != null ? task.getLaunchStackId() : 1644 bounds != null ? FREEFORM_WORKSPACE_STACK_ID : 1645 FULLSCREEN_WORKSPACE_STACK_ID; 1646 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP); 1647 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r=" 1648 + r + " stackId=" + stack.mStackId); 1649 return stack; 1650 } 1651 1652 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task, 1653 ActivityOptions aOptions, boolean launchToSideAllowed) { 1654 final int launchStackId = 1655 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID; 1656 1657 if (isValidLaunchStackId(launchStackId, r)) { 1658 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP); 1659 } 1660 1661 if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_TO_SIDE) == 0) { 1662 return null; 1663 } 1664 1665 // The parent activity doesn't want to launch the activity on top of itself, but 1666 // instead tries to put it onto other side in side-by-side mode. 1667 final ActivityStack parentStack = task != null ? task.stack 1668 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack 1669 : mSupervisor.mFocusedStack; 1670 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) { 1671 // If parent was in docked stack, the natural place to launch another activity 1672 // will be fullscreen, so it can appear alongside the docked window. 1673 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP); 1674 } else { 1675 // If the parent is not in the docked stack, we check if there is docked window 1676 // and if yes, we will launch into that stack. If not, we just put the new 1677 // activity into parent's stack, because we can't find a better place. 1678 final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID); 1679 if (stack != null && !stack.isStackVisibleLocked()) { 1680 // There is a docked stack, but it isn't visible, so we can't launch into that. 1681 return null; 1682 } else { 1683 return stack; 1684 } 1685 } 1686 } 1687 1688 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) { 1689 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID 1690 || !StackId.isStaticStack(stackId)) { 1691 return false; 1692 } 1693 1694 final boolean resizeable = r.isResizeable() || mService.mForceResizableActivities; 1695 1696 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !resizeable) { 1697 return false; 1698 } 1699 1700 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) { 1701 return false; 1702 } 1703 1704 final boolean supportsPip = mService.mSupportsPictureInPicture 1705 && (r.supportsPictureInPicture() || mService.mForceResizableActivities); 1706 if (stackId == PINNED_STACK_ID && !supportsPip) { 1707 return false; 1708 } 1709 return true; 1710 } 1711 1712 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) { 1713 Rect newBounds = null; 1714 if (options != null && (r.isResizeable() || (inTask != null && inTask.mResizeable))) { 1715 if (mSupervisor.canUseActivityOptionsLaunchBounds( 1716 options, options.getLaunchStackId())) { 1717 newBounds = options.getLaunchBounds(); 1718 } 1719 } 1720 return newBounds; 1721 } 1722 1723 void setWindowManager(WindowManagerService wm) { 1724 mWindowManager = wm; 1725 } 1726 1727 void removePendingActivityLaunchesLocked(ActivityStack stack) { 1728 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) { 1729 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx); 1730 if (pal.stack == stack) { 1731 mPendingActivityLaunches.remove(palNdx); 1732 } 1733 } 1734 } 1735} 1736