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