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