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