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