1 /* 2 * Copyright (C) 2017 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.wm; 18 19 import static android.app.ActivityManager.START_SUCCESS; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 21 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 22 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 23 import static android.os.FactoryTest.FACTORY_TEST_LOW_LEVEL; 24 25 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; 26 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 27 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 28 29 import android.annotation.Nullable; 30 import android.app.ActivityOptions; 31 import android.app.IApplicationThread; 32 import android.content.ComponentName; 33 import android.content.ContentResolver; 34 import android.content.Intent; 35 import android.content.pm.ActivityInfo; 36 import android.content.pm.ApplicationInfo; 37 import android.content.pm.PackageManager; 38 import android.content.pm.ResolveInfo; 39 import android.os.Binder; 40 import android.os.Handler; 41 import android.os.IBinder; 42 import android.os.Looper; 43 import android.os.Message; 44 import android.os.UserHandle; 45 import android.provider.Settings; 46 import android.util.Slog; 47 import android.util.SparseArray; 48 import android.util.proto.ProtoOutputStream; 49 import android.view.RemoteAnimationAdapter; 50 51 import com.android.internal.annotations.VisibleForTesting; 52 import com.android.internal.util.ArrayUtils; 53 import com.android.server.am.ActivityManagerService; 54 import com.android.server.am.PendingIntentRecord; 55 import com.android.server.uri.NeededUriGrants; 56 import com.android.server.wm.ActivityStackSupervisor.PendingActivityLaunch; 57 import com.android.server.wm.ActivityStarter.DefaultFactory; 58 import com.android.server.wm.ActivityStarter.Factory; 59 60 import java.io.PrintWriter; 61 import java.util.ArrayList; 62 import java.util.List; 63 64 /** 65 * Controller for delegating activity launches. 66 * 67 * This class' main objective is to take external activity start requests and prepare them into 68 * a series of discrete activity launches that can be handled by an {@link ActivityStarter}. It is 69 * also responsible for handling logic that happens around an activity launch, but doesn't 70 * necessarily influence the activity start. Examples include power hint management, processing 71 * through the pending activity list, and recording home activity launches. 72 */ 73 public class ActivityStartController { 74 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStartController" : TAG_ATM; 75 76 private static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 1; 77 78 private final ActivityTaskManagerService mService; 79 private final ActivityStackSupervisor mSupervisor; 80 81 /** Last home activity record we attempted to start. */ 82 private ActivityRecord mLastHomeActivityStartRecord; 83 84 /** Temporary array to capture start activity results */ 85 private ActivityRecord[] tmpOutRecord = new ActivityRecord[1]; 86 87 /** The result of the last home activity we attempted to start. */ 88 private int mLastHomeActivityStartResult; 89 90 /** A list of activities that are waiting to launch. */ 91 private final ArrayList<ActivityStackSupervisor.PendingActivityLaunch> 92 mPendingActivityLaunches = new ArrayList<>(); 93 94 private final Factory mFactory; 95 96 private final Handler mHandler; 97 98 private final PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry; 99 100 boolean mCheckedForSetup = false; 101 102 private final class StartHandler extends Handler { StartHandler(Looper looper)103 public StartHandler(Looper looper) { 104 super(looper, null, true); 105 } 106 107 @Override handleMessage(Message msg)108 public void handleMessage(Message msg) { 109 switch(msg.what) { 110 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: 111 synchronized (mService.mGlobalLock) { 112 doPendingActivityLaunches(true); 113 } 114 break; 115 } 116 } 117 } 118 119 /** 120 * TODO(b/64750076): Capture information necessary for dump and 121 * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object 122 * around 123 */ 124 private ActivityStarter mLastStarter; 125 ActivityStartController(ActivityTaskManagerService service)126 ActivityStartController(ActivityTaskManagerService service) { 127 this(service, service.mStackSupervisor, 128 new DefaultFactory(service, service.mStackSupervisor, 129 new ActivityStartInterceptor(service, service.mStackSupervisor))); 130 } 131 132 @VisibleForTesting ActivityStartController(ActivityTaskManagerService service, ActivityStackSupervisor supervisor, Factory factory)133 ActivityStartController(ActivityTaskManagerService service, ActivityStackSupervisor supervisor, 134 Factory factory) { 135 mService = service; 136 mSupervisor = supervisor; 137 mHandler = new StartHandler(mService.mH.getLooper()); 138 mFactory = factory; 139 mFactory.setController(this); 140 mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service.mGlobalLock, 141 service.mH); 142 } 143 144 /** 145 * @return A starter to configure and execute starting an activity. It is valid until after 146 * {@link ActivityStarter#execute} is invoked. At that point, the starter should be 147 * considered invalid and no longer modified or used. 148 */ obtainStarter(Intent intent, String reason)149 ActivityStarter obtainStarter(Intent intent, String reason) { 150 return mFactory.obtain().setIntent(intent).setReason(reason); 151 } 152 onExecutionComplete(ActivityStarter starter)153 void onExecutionComplete(ActivityStarter starter) { 154 if (mLastStarter == null) { 155 mLastStarter = mFactory.obtain(); 156 } 157 158 mLastStarter.set(starter); 159 mFactory.recycle(starter); 160 } 161 162 /** 163 * TODO(b/64750076): usage of this doesn't seem right. We're making decisions based off the 164 * last starter for an arbitrary task record. Re-evaluate whether we can remove. 165 */ postStartActivityProcessingForLastStarter(ActivityRecord r, int result, ActivityStack targetStack)166 void postStartActivityProcessingForLastStarter(ActivityRecord r, int result, 167 ActivityStack targetStack) { 168 if (mLastStarter == null) { 169 return; 170 } 171 172 mLastStarter.postStartActivityProcessing(r, result, targetStack); 173 } 174 startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, TaskDisplayArea taskDisplayArea)175 void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, 176 TaskDisplayArea taskDisplayArea) { 177 final ActivityOptions options = ActivityOptions.makeBasic(); 178 options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN); 179 if (!ActivityRecord.isResolverActivity(aInfo.name)) { 180 // The resolver activity shouldn't be put in home stack because when the foreground is 181 // standard type activity, the resolver activity should be put on the top of current 182 // foreground instead of bring home stack to front. 183 options.setLaunchActivityType(ACTIVITY_TYPE_HOME); 184 } 185 final int displayId = taskDisplayArea.getDisplayId(); 186 options.setLaunchDisplayId(displayId); 187 options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken 188 .toWindowContainerToken()); 189 190 // The home activity will be started later, defer resuming to avoid unneccerary operations 191 // (e.g. start home recursively) when creating home stack. 192 mSupervisor.beginDeferResume(); 193 final ActivityStack homeStack; 194 try { 195 // Make sure home stack exists on display area. 196 homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP); 197 } finally { 198 mSupervisor.endDeferResume(); 199 } 200 201 mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason) 202 .setOutActivity(tmpOutRecord) 203 .setCallingUid(0) 204 .setActivityInfo(aInfo) 205 .setActivityOptions(options.toBundle()) 206 .execute(); 207 mLastHomeActivityStartRecord = tmpOutRecord[0]; 208 if (homeStack.mInResumeTopActivity) { 209 // If we are in resume section already, home activity will be initialized, but not 210 // resumed (to avoid recursive resume) and will stay that way until something pokes it 211 // again. We need to schedule another resume. 212 mSupervisor.scheduleResumeTopActivities(); 213 } 214 } 215 216 /** 217 * Starts the "new version setup screen" if appropriate. 218 */ startSetupActivity()219 void startSetupActivity() { 220 // Only do this once per boot. 221 if (mCheckedForSetup) { 222 return; 223 } 224 225 // We will show this screen if the current one is a different 226 // version than the last one shown, and we are not running in 227 // low-level factory test mode. 228 final ContentResolver resolver = mService.mContext.getContentResolver(); 229 if (mService.mFactoryTest != FACTORY_TEST_LOW_LEVEL 230 && Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0) { 231 mCheckedForSetup = true; 232 233 // See if we should be showing the platform update setup UI. 234 final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP); 235 final List<ResolveInfo> ris = 236 mService.mContext.getPackageManager().queryIntentActivities(intent, 237 PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA 238 | ActivityManagerService.STOCK_PM_FLAGS); 239 if (!ris.isEmpty()) { 240 final ResolveInfo ri = ris.get(0); 241 String vers = ri.activityInfo.metaData != null 242 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION) 243 : null; 244 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) { 245 vers = ri.activityInfo.applicationInfo.metaData.getString( 246 Intent.METADATA_SETUP_VERSION); 247 } 248 String lastVers = Settings.Secure.getString( 249 resolver, Settings.Secure.LAST_SETUP_SHOWN); 250 if (vers != null && !vers.equals(lastVers)) { 251 intent.setFlags(FLAG_ACTIVITY_NEW_TASK); 252 intent.setComponent(new ComponentName( 253 ri.activityInfo.packageName, ri.activityInfo.name)); 254 obtainStarter(intent, "startSetupActivity") 255 .setCallingUid(0) 256 .setActivityInfo(ri.activityInfo) 257 .execute(); 258 } 259 } 260 } 261 } 262 263 /** 264 * If {@code validateIncomingUser} is true, check {@code targetUserId} against the real calling 265 * user ID inferred from {@code realCallingUid}, then return the resolved user-id, taking into 266 * account "current user", etc. 267 * 268 * If {@code validateIncomingUser} is false, it skips the above check, but instead 269 * ensures {@code targetUserId} is a real user ID and not a special user ID such as 270 * {@link android.os.UserHandle#USER_ALL}, etc. 271 */ checkTargetUser(int targetUserId, boolean validateIncomingUser, int realCallingPid, int realCallingUid, String reason)272 int checkTargetUser(int targetUserId, boolean validateIncomingUser, 273 int realCallingPid, int realCallingUid, String reason) { 274 if (validateIncomingUser) { 275 return mService.handleIncomingUser( 276 realCallingPid, realCallingUid, targetUserId, reason); 277 } else { 278 mService.mAmInternal.ensureNotSpecialUser(targetUserId); 279 return targetUserId; 280 } 281 } 282 startActivityInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, SafeActivityOptions options, int userId, Task inTask, String reason, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)283 final int startActivityInPackage(int uid, int realCallingPid, int realCallingUid, 284 String callingPackage, @Nullable String callingFeatureId, Intent intent, 285 String resolvedType, IBinder resultTo, String resultWho, int requestCode, 286 int startFlags, SafeActivityOptions options, int userId, Task inTask, String reason, 287 boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, 288 boolean allowBackgroundActivityStart) { 289 290 userId = checkTargetUser(userId, validateIncomingUser, realCallingPid, realCallingUid, 291 reason); 292 293 // TODO: Switch to user app stacks here. 294 return obtainStarter(intent, reason) 295 .setCallingUid(uid) 296 .setRealCallingPid(realCallingPid) 297 .setRealCallingUid(realCallingUid) 298 .setCallingPackage(callingPackage) 299 .setCallingFeatureId(callingFeatureId) 300 .setResolvedType(resolvedType) 301 .setResultTo(resultTo) 302 .setResultWho(resultWho) 303 .setRequestCode(requestCode) 304 .setStartFlags(startFlags) 305 .setActivityOptions(options) 306 .setUserId(userId) 307 .setInTask(inTask) 308 .setOriginatingPendingIntent(originatingPendingIntent) 309 .setAllowBackgroundActivityStart(allowBackgroundActivityStart) 310 .execute(); 311 } 312 313 /** 314 * Start intents as a package. 315 * 316 * @param uid Make a call as if this UID did. 317 * @param callingPackage Make a call as if this package did. 318 * @param callingFeatureId Make a call as if this feature in the package did. 319 * @param intents Intents to start. 320 * @param userId Start the intents on this user. 321 * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID. 322 * @param originatingPendingIntent PendingIntentRecord that originated this activity start or 323 * null if not originated by PendingIntent 324 */ startActivitiesInPackage(int uid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)325 final int startActivitiesInPackage(int uid, String callingPackage, 326 @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, 327 IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, 328 PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { 329 return startActivitiesInPackage(uid, 0 /* realCallingPid */, -1 /* realCallingUid */, 330 callingPackage, callingFeatureId, intents, resolvedTypes, resultTo, options, userId, 331 validateIncomingUser, originatingPendingIntent, allowBackgroundActivityStart); 332 } 333 334 /** 335 * Start intents as a package. 336 * 337 * @param uid Make a call as if this UID did. 338 * @param realCallingPid PID of the real caller. 339 * @param realCallingUid UID of the real caller. 340 * @param callingPackage Make a call as if this package did. 341 * @param intents Intents to start. 342 * @param userId Start the intents on this user. 343 * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID. 344 * @param originatingPendingIntent PendingIntentRecord that originated this activity start or 345 * null if not originated by PendingIntent 346 */ startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)347 final int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, 348 String callingPackage, @Nullable String callingFeatureId, Intent[] intents, 349 String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, 350 boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, 351 boolean allowBackgroundActivityStart) { 352 353 final String reason = "startActivityInPackage"; 354 355 userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), 356 Binder.getCallingUid(), reason); 357 358 // TODO: Switch to user app stacks here. 359 return startActivities(null, uid, realCallingPid, realCallingUid, callingPackage, 360 callingFeatureId, intents, resolvedTypes, resultTo, options, userId, reason, 361 originatingPendingIntent, allowBackgroundActivityStart); 362 } 363 startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, int incomingRealCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)364 int startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, 365 int incomingRealCallingUid, String callingPackage, @Nullable String callingFeatureId, 366 Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, 367 int userId, String reason, PendingIntentRecord originatingPendingIntent, 368 boolean allowBackgroundActivityStart) { 369 if (intents == null) { 370 throw new NullPointerException("intents is null"); 371 } 372 if (resolvedTypes == null) { 373 throw new NullPointerException("resolvedTypes is null"); 374 } 375 if (intents.length != resolvedTypes.length) { 376 throw new IllegalArgumentException("intents are length different than resolvedTypes"); 377 } 378 379 final int realCallingPid = incomingRealCallingPid != 0 380 ? incomingRealCallingPid 381 : Binder.getCallingPid(); 382 final int realCallingUid = incomingRealCallingUid != -1 383 ? incomingRealCallingUid 384 : Binder.getCallingUid(); 385 386 int callingPid; 387 if (callingUid >= 0) { 388 callingPid = -1; 389 } else if (caller == null) { 390 callingPid = realCallingPid; 391 callingUid = realCallingUid; 392 } else { 393 callingPid = callingUid = -1; 394 } 395 final int filterCallingUid = ActivityStarter.computeResolveFilterUid( 396 callingUid, realCallingUid, UserHandle.USER_NULL); 397 final SparseArray<String> startingUidPkgs = new SparseArray<>(); 398 final long origId = Binder.clearCallingIdentity(); 399 try { 400 intents = ArrayUtils.filterNotNull(intents, Intent[]::new); 401 final ActivityStarter[] starters = new ActivityStarter[intents.length]; 402 // Do not hold WM global lock on this loop because when resolving intent, it may 403 // potentially acquire activity manager lock that leads to deadlock. 404 for (int i = 0; i < intents.length; i++) { 405 Intent intent = intents[i]; 406 NeededUriGrants intentGrants = null; 407 408 // Refuse possible leaked file descriptors. 409 if (intent.hasFileDescriptors()) { 410 throw new IllegalArgumentException("File descriptors passed in Intent"); 411 } 412 413 // Get the flag earlier because the intent may be modified in resolveActivity below. 414 final boolean componentSpecified = intent.getComponent() != null; 415 // Don't modify the client's object! 416 intent = new Intent(intent); 417 418 // Collect information about the target of the Intent. 419 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 420 0 /* startFlags */, null /* profilerInfo */, userId, filterCallingUid); 421 aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId); 422 423 // Carefully collect grants without holding lock 424 if (aInfo != null) { 425 intentGrants = mSupervisor.mService.mUgmInternal 426 .checkGrantUriPermissionFromIntent(intent, filterCallingUid, 427 aInfo.applicationInfo.packageName, 428 UserHandle.getUserId(aInfo.applicationInfo.uid)); 429 } 430 431 if (aInfo != null) { 432 if ((aInfo.applicationInfo.privateFlags 433 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { 434 throw new IllegalArgumentException( 435 "FLAG_CANT_SAVE_STATE not supported here"); 436 } 437 startingUidPkgs.put(aInfo.applicationInfo.uid, 438 aInfo.applicationInfo.packageName); 439 } 440 441 final boolean top = i == intents.length - 1; 442 final SafeActivityOptions checkedOptions = top 443 ? options 444 : null; 445 starters[i] = obtainStarter(intent, reason) 446 .setIntentGrants(intentGrants) 447 .setCaller(caller) 448 .setResolvedType(resolvedTypes[i]) 449 .setActivityInfo(aInfo) 450 .setRequestCode(-1) 451 .setCallingPid(callingPid) 452 .setCallingUid(callingUid) 453 .setCallingPackage(callingPackage) 454 .setCallingFeatureId(callingFeatureId) 455 .setRealCallingPid(realCallingPid) 456 .setRealCallingUid(realCallingUid) 457 .setActivityOptions(checkedOptions) 458 .setComponentSpecified(componentSpecified) 459 460 // Top activity decides on animation being run, so we allow only for the 461 // top one as otherwise an activity below might consume it. 462 .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/) 463 .setOriginatingPendingIntent(originatingPendingIntent) 464 .setAllowBackgroundActivityStart(allowBackgroundActivityStart); 465 } 466 // Log if the activities to be started have different uids. 467 if (startingUidPkgs.size() > 1) { 468 final StringBuilder sb = new StringBuilder("startActivities: different apps ["); 469 final int size = startingUidPkgs.size(); 470 for (int i = 0; i < size; i++) { 471 sb.append(startingUidPkgs.valueAt(i)).append(i == size - 1 ? "]" : ", "); 472 } 473 sb.append(" from ").append(callingPackage); 474 Slog.wtf(TAG, sb.toString()); 475 } 476 477 final IBinder sourceResultTo = resultTo; 478 final ActivityRecord[] outActivity = new ActivityRecord[1]; 479 // Lock the loop to ensure the activities launched in a sequence. 480 synchronized (mService.mGlobalLock) { 481 mService.deferWindowLayout(); 482 try { 483 for (int i = 0; i < starters.length; i++) { 484 final int startResult = starters[i].setResultTo(resultTo) 485 .setOutActivity(outActivity).execute(); 486 if (startResult < START_SUCCESS) { 487 // Abort by error result and recycle unused starters. 488 for (int j = i + 1; j < starters.length; j++) { 489 mFactory.recycle(starters[j]); 490 } 491 return startResult; 492 } 493 final ActivityRecord started = outActivity[0]; 494 if (started != null && started.getUid() == filterCallingUid) { 495 // Only the started activity which has the same uid as the source caller 496 // can be the caller of next activity. 497 resultTo = started.appToken; 498 } else { 499 resultTo = sourceResultTo; 500 // Different apps not adjacent to the caller are forced to be new task. 501 if (i < starters.length - 1) { 502 starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 503 } 504 } 505 } 506 } finally { 507 mService.continueWindowLayout(); 508 } 509 } 510 } finally { 511 Binder.restoreCallingIdentity(origId); 512 } 513 514 return START_SUCCESS; 515 } 516 schedulePendingActivityLaunches(long delayMs)517 void schedulePendingActivityLaunches(long delayMs) { 518 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG); 519 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG); 520 mHandler.sendMessageDelayed(msg, delayMs); 521 } 522 doPendingActivityLaunches(boolean doResume)523 void doPendingActivityLaunches(boolean doResume) { 524 while (!mPendingActivityLaunches.isEmpty()) { 525 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); 526 final boolean resume = doResume && mPendingActivityLaunches.isEmpty(); 527 final ActivityStarter starter = obtainStarter(null /* intent */, 528 "pendingActivityLaunch"); 529 try { 530 starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, 531 resume, pal.r.pendingOptions, null, pal.intentGrants); 532 } catch (Exception e) { 533 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e); 534 pal.sendErrorResult(e.getMessage()); 535 } 536 } 537 } 538 addPendingActivityLaunch(PendingActivityLaunch launch)539 void addPendingActivityLaunch(PendingActivityLaunch launch) { 540 mPendingActivityLaunches.add(launch); 541 } 542 clearPendingActivityLaunches(String packageName)543 boolean clearPendingActivityLaunches(String packageName) { 544 final int pendingLaunches = mPendingActivityLaunches.size(); 545 546 for (int palNdx = pendingLaunches - 1; palNdx >= 0; --palNdx) { 547 final PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx); 548 final ActivityRecord r = pal.r; 549 if (r != null && r.packageName.equals(packageName)) { 550 mPendingActivityLaunches.remove(palNdx); 551 } 552 } 553 return mPendingActivityLaunches.size() < pendingLaunches; 554 } 555 registerRemoteAnimationForNextActivityStart(String packageName, RemoteAnimationAdapter adapter)556 void registerRemoteAnimationForNextActivityStart(String packageName, 557 RemoteAnimationAdapter adapter) { 558 mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter); 559 } 560 getPendingRemoteAnimationRegistry()561 PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() { 562 return mPendingRemoteAnimationRegistry; 563 } 564 dumpLastHomeActivityStartResult(PrintWriter pw, String prefix)565 void dumpLastHomeActivityStartResult(PrintWriter pw, String prefix) { 566 pw.print(prefix); 567 pw.print("mLastHomeActivityStartResult="); 568 pw.println(mLastHomeActivityStartResult); 569 } 570 dump(PrintWriter pw, String prefix, String dumpPackage)571 void dump(PrintWriter pw, String prefix, String dumpPackage) { 572 boolean dumped = false; 573 574 final boolean dumpPackagePresent = dumpPackage != null; 575 576 if (mLastHomeActivityStartRecord != null && (!dumpPackagePresent 577 || dumpPackage.equals(mLastHomeActivityStartRecord.packageName))) { 578 if (!dumped) { 579 dumped = true; 580 dumpLastHomeActivityStartResult(pw, prefix); 581 } 582 pw.print(prefix); 583 pw.println("mLastHomeActivityStartRecord:"); 584 mLastHomeActivityStartRecord.dump(pw, prefix + " ", true /* dumpAll */); 585 } 586 587 if (mLastStarter != null) { 588 final boolean dump = !dumpPackagePresent 589 || mLastStarter.relatedToPackage(dumpPackage) 590 || (mLastHomeActivityStartRecord != null 591 && dumpPackage.equals(mLastHomeActivityStartRecord.packageName)); 592 593 if (dump) { 594 if (!dumped) { 595 dumped = true; 596 dumpLastHomeActivityStartResult(pw, prefix); 597 } 598 pw.print(prefix); 599 mLastStarter.dump(pw, prefix + " "); 600 601 if (dumpPackagePresent) { 602 return; 603 } 604 } 605 } 606 607 if (!dumped) { 608 pw.print(prefix); 609 pw.println("(nothing)"); 610 } 611 } 612 dumpDebug(ProtoOutputStream proto, long fieldId)613 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 614 for (PendingActivityLaunch activity: mPendingActivityLaunches) { 615 activity.r.writeIdentifierToProto(proto, fieldId); 616 } 617 } 618 } 619