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