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