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