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