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