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