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