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