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