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