1 /* 2 * Copyright (C) 2018 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.PROCESS_STATE_NONEXISTENT; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 21 import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED; 22 import static android.os.Build.VERSION_CODES.Q; 23 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 24 25 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; 26 import static com.android.internal.util.Preconditions.checkArgument; 27 import static com.android.server.am.ActivityManagerService.MY_PID; 28 import static com.android.server.wm.ActivityRecord.State.DESTROYED; 29 import static com.android.server.wm.ActivityRecord.State.DESTROYING; 30 import static com.android.server.wm.ActivityRecord.State.PAUSED; 31 import static com.android.server.wm.ActivityRecord.State.PAUSING; 32 import static com.android.server.wm.ActivityRecord.State.RESUMED; 33 import static com.android.server.wm.ActivityRecord.State.STARTED; 34 import static com.android.server.wm.ActivityRecord.State.STOPPING; 35 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; 36 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; 37 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; 38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 39 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 40 import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS; 41 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; 42 43 import android.Manifest; 44 import android.annotation.NonNull; 45 import android.annotation.Nullable; 46 import android.app.ActivityManager; 47 import android.app.ActivityThread; 48 import android.app.IApplicationThread; 49 import android.app.ProfilerInfo; 50 import android.app.servertransaction.ConfigurationChangeItem; 51 import android.content.Context; 52 import android.content.Intent; 53 import android.content.pm.ActivityInfo; 54 import android.content.pm.ApplicationInfo; 55 import android.content.pm.ServiceInfo; 56 import android.content.res.Configuration; 57 import android.os.Binder; 58 import android.os.Build; 59 import android.os.IBinder; 60 import android.os.LocaleList; 61 import android.os.Message; 62 import android.os.Process; 63 import android.os.RemoteException; 64 import android.util.ArraySet; 65 import android.util.Log; 66 import android.util.Slog; 67 import android.util.proto.ProtoOutputStream; 68 import android.view.IRemoteAnimationRunner; 69 70 import com.android.internal.annotations.VisibleForTesting; 71 import com.android.internal.app.HeavyWeightSwitcherActivity; 72 import com.android.internal.protolog.common.ProtoLog; 73 import com.android.internal.util.function.pooled.PooledLambda; 74 import com.android.server.Watchdog; 75 import com.android.server.wm.ActivityTaskManagerService.HotPath; 76 77 import java.io.IOException; 78 import java.io.PrintWriter; 79 import java.lang.ref.WeakReference; 80 import java.util.ArrayList; 81 import java.util.List; 82 83 /** 84 * The Activity Manager (AM) package manages the lifecycle of processes in the system through 85 * ProcessRecord. However, it is important for the Window Manager (WM) package to be aware 86 * of the processes and their state since it affects how WM manages windows and activities. This 87 * class that allows the ProcessRecord object in the AM package to communicate important 88 * changes to its state to the WM package in a structured way. WM package also uses 89 * {@link WindowProcessListener} to request changes to the process state on the AM side. 90 * Note that public calls into this class are assumed to be originating from outside the 91 * window manager so the window manager lock is held and appropriate permissions are checked before 92 * calls are allowed to proceed. 93 */ 94 public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer> 95 implements ConfigurationContainerListener { 96 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM; 97 private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; 98 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; 99 100 // all about the first app in the process 101 final ApplicationInfo mInfo; 102 final String mName; 103 final int mUid; 104 105 // The process of this application; 0 if none 106 private volatile int mPid; 107 // user of process. 108 final int mUserId; 109 // The owner of this window process controller object. Mainly for identification when we 110 // communicate back to the activity manager side. 111 public final Object mOwner; 112 // List of packages running in the process 113 final ArraySet<String> mPkgList = new ArraySet<>(); 114 private final WindowProcessListener mListener; 115 private final ActivityTaskManagerService mAtm; 116 private final BackgroundLaunchProcessController mBgLaunchController; 117 // The actual proc... may be null only if 'persistent' is true (in which case we are in the 118 // process of launching the app) 119 private IApplicationThread mThread; 120 // Currently desired scheduling class 121 private volatile int mCurSchedGroup; 122 // Currently computed process state 123 private volatile int mCurProcState = PROCESS_STATE_NONEXISTENT; 124 // Last reported process state; 125 private volatile int mRepProcState = PROCESS_STATE_NONEXISTENT; 126 // are we in the process of crashing? 127 private volatile boolean mCrashing; 128 // does the app have a not responding dialog? 129 private volatile boolean mNotResponding; 130 // always keep this application running? 131 private volatile boolean mPersistent; 132 // The ABI this process was launched with 133 private volatile String mRequiredAbi; 134 // Running any services that are foreground? 135 private volatile boolean mHasForegroundServices; 136 // Are there any client services with activities? 137 private volatile boolean mHasClientActivities; 138 // Is this process currently showing a non-activity UI that the user is interacting with? 139 // E.g. The status bar when it is expanded, but not when it is minimized. When true the process 140 // will be set to use the ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost performance. 141 private volatile boolean mHasTopUi; 142 // Is the process currently showing a non-activity UI that overlays on-top of activity UIs on 143 // screen. E.g. display a window of type 144 // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY When true the process will 145 // oom adj score will be set to ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance 146 // of the process getting killed. 147 private volatile boolean mHasOverlayUi; 148 // Want to clean up resources from showing UI? 149 private volatile boolean mPendingUiClean; 150 // The time we sent the last interaction event 151 private volatile long mInteractionEventTime; 152 // When we became foreground for interaction purposes 153 private volatile long mFgInteractionTime; 154 // When (uptime) the process last became unimportant 155 private volatile long mWhenUnimportant; 156 // was app launched for debugging? 157 private volatile boolean mDebugging; 158 // Active instrumentation running in process? 159 private volatile boolean mInstrumenting; 160 // If there is active instrumentation, this is the source 161 private volatile int mInstrumentationSourceUid = -1; 162 // Active instrumentation with background activity starts privilege running in process? 163 private volatile boolean mInstrumentingWithBackgroundActivityStartPrivileges; 164 // This process it perceptible by the user. 165 private volatile boolean mPerceptible; 166 // Set to true when process was launched with a wrapper attached 167 private volatile boolean mUsingWrapper; 168 169 // Thread currently set for VR scheduling 170 int mVrThreadTid; 171 172 // Whether this process has ever started a service with the BIND_INPUT_METHOD permission. 173 private volatile boolean mHasImeService; 174 175 /** Whether {@link #mActivities} is not empty. */ 176 private volatile boolean mHasActivities; 177 /** All activities running in the process (exclude destroying). */ 178 private final ArrayList<ActivityRecord> mActivities = new ArrayList<>(); 179 /** The activities will be removed but still belong to this process. */ 180 private ArrayList<ActivityRecord> mInactiveActivities; 181 /** Whether {@link #mRecentTasks} is not empty. */ 182 private volatile boolean mHasRecentTasks; 183 // any tasks this process had run root activities in 184 private final ArrayList<Task> mRecentTasks = new ArrayList<>(); 185 // The most recent top-most activity that was resumed in the process for pre-Q app. 186 private ActivityRecord mPreQTopResumedActivity = null; 187 // The last time an activity was launched in the process 188 private volatile long mLastActivityLaunchTime; 189 // The last time an activity was finished in the process while the process participated 190 // in a visible task 191 private volatile long mLastActivityFinishTime; 192 193 // Last configuration that was reported to the process. 194 private final Configuration mLastReportedConfiguration = new Configuration(); 195 /** Whether the process configuration is waiting to be dispatched to the process. */ 196 private boolean mHasPendingConfigurationChange; 197 198 /** 199 * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not 200 * registered. 201 */ 202 @Nullable 203 private DisplayArea mDisplayArea; 204 private ActivityRecord mConfigActivityRecord; 205 // Whether the activity config override is allowed for this process. 206 private volatile boolean mIsActivityConfigOverrideAllowed = true; 207 /** Non-zero to pause dispatching process configuration change. */ 208 private int mPauseConfigurationDispatchCount; 209 210 /** 211 * Activities that hosts some UI drawn by the current process. The activities live 212 * in another process. This is used to check if the process is currently showing anything 213 * visible to the user. 214 */ 215 @Nullable 216 private final ArrayList<ActivityRecord> mHostActivities = new ArrayList<>(); 217 218 /** Whether our process is currently running a {@link RecentsAnimation} */ 219 private boolean mRunningRecentsAnimation; 220 221 /** Whether our process is currently running a {@link IRemoteAnimationRunner} */ 222 private boolean mRunningRemoteAnimation; 223 224 /** List of "chained" processes that are running remote animations for this process */ 225 private final ArrayList<WeakReference<WindowProcessController>> mRemoteAnimationDelegates = 226 new ArrayList<>(); 227 228 // The bits used for mActivityStateFlags. 229 private static final int ACTIVITY_STATE_FLAG_IS_VISIBLE = 1 << 16; 230 private static final int ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED = 1 << 17; 231 private static final int ACTIVITY_STATE_FLAG_IS_STOPPING = 1 << 18; 232 private static final int ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING = 1 << 19; 233 private static final int ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE = 1 << 20; 234 private static final int ACTIVITY_STATE_FLAG_HAS_RESUMED = 1 << 21; 235 private static final int ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK = 1 << 22; 236 private static final int ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER = 0x0000ffff; 237 238 /** 239 * The state for oom-adjustment calculation. The higher 16 bits are the activity states, and the 240 * lower 16 bits are the task layer rank (see {@link Task#mLayerRank}). This field is written by 241 * window manager and read by activity manager. 242 */ 243 private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; 244 WindowProcessController(@onNull ActivityTaskManagerService atm, @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner, @NonNull WindowProcessListener listener)245 public WindowProcessController(@NonNull ActivityTaskManagerService atm, 246 @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner, 247 @NonNull WindowProcessListener listener) { 248 mInfo = info; 249 mName = name; 250 mUid = uid; 251 mUserId = userId; 252 mOwner = owner; 253 mListener = listener; 254 mAtm = atm; 255 mBgLaunchController = new BackgroundLaunchProcessController( 256 atm::hasActiveVisibleWindow, atm.getBackgroundActivityStartCallback()); 257 258 boolean isSysUiPackage = info.packageName.equals( 259 mAtm.getSysUiServiceComponentLocked().getPackageName()); 260 if (isSysUiPackage || mUid == Process.SYSTEM_UID) { 261 // This is a system owned process and should not use an activity config. 262 // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs. 263 mIsActivityConfigOverrideAllowed = false; 264 } 265 266 onConfigurationChanged(atm.getGlobalConfiguration()); 267 mAtm.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, mInfo.packageName); 268 } 269 setPid(int pid)270 public void setPid(int pid) { 271 mPid = pid; 272 } 273 getPid()274 public int getPid() { 275 return mPid; 276 } 277 278 @HotPath(caller = HotPath.PROCESS_CHANGE) setThread(IApplicationThread thread)279 public void setThread(IApplicationThread thread) { 280 synchronized (mAtm.mGlobalLockWithoutBoost) { 281 mThread = thread; 282 // In general this is called from attaching application, so the last configuration 283 // has been sent to client by {@link android.app.IApplicationThread#bindApplication}. 284 // If this process is system server, it is fine because system is booting and a new 285 // configuration will update when display is ready. 286 if (thread != null) { 287 setLastReportedConfiguration(getConfiguration()); 288 } else { 289 // The process is inactive. 290 mAtm.mVisibleActivityProcessTracker.removeProcess(this); 291 } 292 } 293 } 294 getThread()295 IApplicationThread getThread() { 296 return mThread; 297 } 298 hasThread()299 boolean hasThread() { 300 return mThread != null; 301 } 302 setCurrentSchedulingGroup(int curSchedGroup)303 public void setCurrentSchedulingGroup(int curSchedGroup) { 304 mCurSchedGroup = curSchedGroup; 305 } 306 getCurrentSchedulingGroup()307 int getCurrentSchedulingGroup() { 308 return mCurSchedGroup; 309 } 310 setCurrentProcState(int curProcState)311 public void setCurrentProcState(int curProcState) { 312 mCurProcState = curProcState; 313 } 314 getCurrentProcState()315 int getCurrentProcState() { 316 return mCurProcState; 317 } 318 setReportedProcState(int repProcState)319 public void setReportedProcState(int repProcState) { 320 mRepProcState = repProcState; 321 } 322 getReportedProcState()323 int getReportedProcState() { 324 return mRepProcState; 325 } 326 setCrashing(boolean crashing)327 public void setCrashing(boolean crashing) { 328 mCrashing = crashing; 329 } 330 isCrashing()331 boolean isCrashing() { 332 return mCrashing; 333 } 334 setNotResponding(boolean notResponding)335 public void setNotResponding(boolean notResponding) { 336 mNotResponding = notResponding; 337 } 338 isNotResponding()339 boolean isNotResponding() { 340 return mNotResponding; 341 } 342 setPersistent(boolean persistent)343 public void setPersistent(boolean persistent) { 344 mPersistent = persistent; 345 } 346 isPersistent()347 boolean isPersistent() { 348 return mPersistent; 349 } 350 setHasForegroundServices(boolean hasForegroundServices)351 public void setHasForegroundServices(boolean hasForegroundServices) { 352 mHasForegroundServices = hasForegroundServices; 353 } 354 hasForegroundServices()355 boolean hasForegroundServices() { 356 return mHasForegroundServices; 357 } 358 hasForegroundActivities()359 boolean hasForegroundActivities() { 360 return mAtm.mTopApp == this || (mActivityStateFlags 361 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED 362 | ACTIVITY_STATE_FLAG_IS_STOPPING)) != 0; 363 } 364 setHasClientActivities(boolean hasClientActivities)365 public void setHasClientActivities(boolean hasClientActivities) { 366 mHasClientActivities = hasClientActivities; 367 } 368 hasClientActivities()369 boolean hasClientActivities() { 370 return mHasClientActivities; 371 } 372 setHasTopUi(boolean hasTopUi)373 public void setHasTopUi(boolean hasTopUi) { 374 mHasTopUi = hasTopUi; 375 } 376 hasTopUi()377 boolean hasTopUi() { 378 return mHasTopUi; 379 } 380 setHasOverlayUi(boolean hasOverlayUi)381 public void setHasOverlayUi(boolean hasOverlayUi) { 382 mHasOverlayUi = hasOverlayUi; 383 } 384 hasOverlayUi()385 boolean hasOverlayUi() { 386 return mHasOverlayUi; 387 } 388 setPendingUiClean(boolean hasPendingUiClean)389 public void setPendingUiClean(boolean hasPendingUiClean) { 390 mPendingUiClean = hasPendingUiClean; 391 } 392 hasPendingUiClean()393 boolean hasPendingUiClean() { 394 return mPendingUiClean; 395 } 396 397 /** @return {@code true} if the process registered to a display area as a config listener. */ registeredForDisplayAreaConfigChanges()398 boolean registeredForDisplayAreaConfigChanges() { 399 return mDisplayArea != null; 400 } 401 402 /** @return {@code true} if the process registered to an activity as a config listener. */ 403 @VisibleForTesting registeredForActivityConfigChanges()404 boolean registeredForActivityConfigChanges() { 405 return mConfigActivityRecord != null; 406 } 407 postPendingUiCleanMsg(boolean pendingUiClean)408 void postPendingUiCleanMsg(boolean pendingUiClean) { 409 // Posting on handler so WM lock isn't held when we call into AM. 410 final Message m = PooledLambda.obtainMessage( 411 WindowProcessListener::setPendingUiClean, mListener, pendingUiClean); 412 mAtm.mH.sendMessage(m); 413 } 414 setInteractionEventTime(long interactionEventTime)415 public void setInteractionEventTime(long interactionEventTime) { 416 mInteractionEventTime = interactionEventTime; 417 } 418 getInteractionEventTime()419 long getInteractionEventTime() { 420 return mInteractionEventTime; 421 } 422 setFgInteractionTime(long fgInteractionTime)423 public void setFgInteractionTime(long fgInteractionTime) { 424 mFgInteractionTime = fgInteractionTime; 425 } 426 getFgInteractionTime()427 long getFgInteractionTime() { 428 return mFgInteractionTime; 429 } 430 setWhenUnimportant(long whenUnimportant)431 public void setWhenUnimportant(long whenUnimportant) { 432 mWhenUnimportant = whenUnimportant; 433 } 434 getWhenUnimportant()435 long getWhenUnimportant() { 436 return mWhenUnimportant; 437 } 438 setRequiredAbi(String requiredAbi)439 public void setRequiredAbi(String requiredAbi) { 440 mRequiredAbi = requiredAbi; 441 } 442 getRequiredAbi()443 String getRequiredAbi() { 444 return mRequiredAbi; 445 } 446 447 /** 448 * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not 449 * registered. 450 */ 451 @VisibleForTesting 452 @Nullable getDisplayArea()453 DisplayArea getDisplayArea() { 454 return mDisplayArea; 455 } 456 setDebugging(boolean debugging)457 public void setDebugging(boolean debugging) { 458 mDebugging = debugging; 459 } 460 isDebugging()461 boolean isDebugging() { 462 return mDebugging; 463 } 464 setUsingWrapper(boolean usingWrapper)465 public void setUsingWrapper(boolean usingWrapper) { 466 mUsingWrapper = usingWrapper; 467 } 468 isUsingWrapper()469 boolean isUsingWrapper() { 470 return mUsingWrapper; 471 } 472 hasEverLaunchedActivity()473 boolean hasEverLaunchedActivity() { 474 return mLastActivityLaunchTime > 0; 475 } 476 setLastActivityLaunchTime(long launchTime)477 void setLastActivityLaunchTime(long launchTime) { 478 if (launchTime <= mLastActivityLaunchTime) { 479 if (launchTime < mLastActivityLaunchTime) { 480 Slog.w(TAG, 481 "Tried to set launchTime (" + launchTime + ") < mLastActivityLaunchTime (" 482 + mLastActivityLaunchTime + ")"); 483 } 484 return; 485 } 486 mLastActivityLaunchTime = launchTime; 487 } 488 setLastActivityFinishTimeIfNeeded(long finishTime)489 void setLastActivityFinishTimeIfNeeded(long finishTime) { 490 if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) { 491 return; 492 } 493 mLastActivityFinishTime = finishTime; 494 } 495 496 /** 497 * @see BackgroundLaunchProcessController#addOrUpdateAllowBackgroundActivityStartsToken(Binder, 498 * IBinder) 499 */ addOrUpdateAllowBackgroundActivityStartsToken(Binder entity, @Nullable IBinder originatingToken)500 public void addOrUpdateAllowBackgroundActivityStartsToken(Binder entity, 501 @Nullable IBinder originatingToken) { 502 mBgLaunchController.addOrUpdateAllowBackgroundActivityStartsToken(entity, originatingToken); 503 } 504 505 /** @see BackgroundLaunchProcessController#removeAllowBackgroundActivityStartsToken(Binder) */ removeAllowBackgroundActivityStartsToken(Binder entity)506 public void removeAllowBackgroundActivityStartsToken(Binder entity) { 507 mBgLaunchController.removeAllowBackgroundActivityStartsToken(entity); 508 } 509 510 /** 511 * Is this WindowProcessController in the state of allowing background FGS start? 512 */ 513 @HotPath(caller = HotPath.START_SERVICE) areBackgroundFgsStartsAllowed()514 public boolean areBackgroundFgsStartsAllowed() { 515 return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesState(), 516 true /* isCheckingForFgsStart */); 517 } 518 areBackgroundActivityStartsAllowed(int appSwitchState)519 boolean areBackgroundActivityStartsAllowed(int appSwitchState) { 520 return areBackgroundActivityStartsAllowed(appSwitchState, 521 false /* isCheckingForFgsStart */); 522 } 523 areBackgroundActivityStartsAllowed(int appSwitchState, boolean isCheckingForFgsStart)524 private boolean areBackgroundActivityStartsAllowed(int appSwitchState, 525 boolean isCheckingForFgsStart) { 526 return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, mInfo.packageName, 527 appSwitchState, isCheckingForFgsStart, hasActivityInVisibleTask(), 528 mInstrumentingWithBackgroundActivityStartPrivileges, 529 mAtm.getLastStopAppSwitchesTime(), 530 mLastActivityLaunchTime, mLastActivityFinishTime); 531 } 532 533 /** 534 * Returns whether this process is allowed to close system dialogs via a background activity 535 * start token that allows the close system dialogs operation (eg. notification). 536 */ canCloseSystemDialogsByToken()537 boolean canCloseSystemDialogsByToken() { 538 return mBgLaunchController.canCloseSystemDialogsByToken(mUid); 539 } 540 setBoundClientUids(ArraySet<Integer> boundClientUids)541 public void setBoundClientUids(ArraySet<Integer> boundClientUids) { 542 mBgLaunchController.setBoundClientUids(boundClientUids); 543 } 544 545 /** 546 * Set instrumentation-related info. 547 * 548 * If {@code instrumenting} is {@code false}, {@code sourceUid} has to be -1. 549 */ setInstrumenting(boolean instrumenting, int sourceUid, boolean hasBackgroundActivityStartPrivileges)550 public void setInstrumenting(boolean instrumenting, int sourceUid, 551 boolean hasBackgroundActivityStartPrivileges) { 552 checkArgument(instrumenting || sourceUid == -1); 553 mInstrumenting = instrumenting; 554 mInstrumentationSourceUid = sourceUid; 555 mInstrumentingWithBackgroundActivityStartPrivileges = hasBackgroundActivityStartPrivileges; 556 } 557 isInstrumenting()558 boolean isInstrumenting() { 559 return mInstrumenting; 560 } 561 562 /** Returns the uid of the active instrumentation source if there is one, otherwise -1. */ getInstrumentationSourceUid()563 int getInstrumentationSourceUid() { 564 return mInstrumentationSourceUid; 565 } 566 setPerceptible(boolean perceptible)567 public void setPerceptible(boolean perceptible) { 568 mPerceptible = perceptible; 569 } 570 isPerceptible()571 boolean isPerceptible() { 572 return mPerceptible; 573 } 574 575 @Override getChildCount()576 protected int getChildCount() { 577 return 0; 578 } 579 580 @Override getChildAt(int index)581 protected ConfigurationContainer getChildAt(int index) { 582 return null; 583 } 584 585 @Override getParent()586 protected ConfigurationContainer getParent() { 587 // Returning RootWindowContainer as the parent, so that this process controller always 588 // has full configuration and overrides (e.g. from display) are always added on top of 589 // global config. 590 return mAtm.mRootWindowContainer; 591 } 592 593 @HotPath(caller = HotPath.PROCESS_CHANGE) addPackage(String packageName)594 public void addPackage(String packageName) { 595 synchronized (mAtm.mGlobalLockWithoutBoost) { 596 mPkgList.add(packageName); 597 } 598 } 599 600 @HotPath(caller = HotPath.PROCESS_CHANGE) clearPackageList()601 public void clearPackageList() { 602 synchronized (mAtm.mGlobalLockWithoutBoost) { 603 mPkgList.clear(); 604 } 605 } 606 addActivityIfNeeded(ActivityRecord r)607 void addActivityIfNeeded(ActivityRecord r) { 608 // even if we already track this activity, note down that it has been launched 609 setLastActivityLaunchTime(r.lastLaunchTime); 610 if (mActivities.contains(r)) { 611 return; 612 } 613 mActivities.add(r); 614 mHasActivities = true; 615 if (mInactiveActivities != null) { 616 mInactiveActivities.remove(r); 617 } 618 updateActivityConfigurationListener(); 619 } 620 621 /** 622 * Indicates that the given activity is no longer active in this process. 623 * 624 * @param r The running activity to be removed. 625 * @param keepAssociation {@code true} if the activity still belongs to this process but will 626 * be removed soon, e.g. destroying. From the perspective of process 627 * priority, the process is not important if it only contains activities 628 * that are being destroyed. But the association is still needed to 629 * ensure all activities are reachable from this process. 630 */ removeActivity(ActivityRecord r, boolean keepAssociation)631 void removeActivity(ActivityRecord r, boolean keepAssociation) { 632 if (keepAssociation) { 633 if (mInactiveActivities == null) { 634 mInactiveActivities = new ArrayList<>(); 635 mInactiveActivities.add(r); 636 } else if (!mInactiveActivities.contains(r)) { 637 mInactiveActivities.add(r); 638 } 639 } else if (mInactiveActivities != null) { 640 mInactiveActivities.remove(r); 641 } 642 mActivities.remove(r); 643 mHasActivities = !mActivities.isEmpty(); 644 updateActivityConfigurationListener(); 645 } 646 clearActivities()647 void clearActivities() { 648 mInactiveActivities = null; 649 mActivities.clear(); 650 mHasActivities = false; 651 updateActivityConfigurationListener(); 652 } 653 654 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasActivities()655 public boolean hasActivities() { 656 return mHasActivities; 657 } 658 659 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasVisibleActivities()660 public boolean hasVisibleActivities() { 661 return (mActivityStateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0; 662 } 663 hasActivityInVisibleTask()664 boolean hasActivityInVisibleTask() { 665 return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0; 666 } 667 668 @HotPath(caller = HotPath.LRU_UPDATE) hasActivitiesOrRecentTasks()669 public boolean hasActivitiesOrRecentTasks() { 670 return mHasActivities || mHasRecentTasks; 671 } 672 673 @Nullable getTopActivityDisplayArea()674 TaskDisplayArea getTopActivityDisplayArea() { 675 if (mActivities.isEmpty()) { 676 return null; 677 } 678 679 final int lastIndex = mActivities.size() - 1; 680 ActivityRecord topRecord = mActivities.get(lastIndex); 681 TaskDisplayArea displayArea = topRecord.getDisplayArea(); 682 683 for (int index = lastIndex - 1; index >= 0; --index) { 684 ActivityRecord nextRecord = mActivities.get(index); 685 TaskDisplayArea nextDisplayArea = nextRecord.getDisplayArea(); 686 if (nextRecord.compareTo(topRecord) > 0 && nextDisplayArea != null) { 687 topRecord = nextRecord; 688 displayArea = nextDisplayArea; 689 } 690 } 691 692 return displayArea; 693 } 694 695 /** 696 * Update the top resuming activity in process for pre-Q apps, only the top-most visible 697 * activities are allowed to be resumed per process. 698 * @return {@code true} if the activity is allowed to be resumed by compatibility 699 * restrictions, which the activity was the topmost visible activity in process or the app is 700 * targeting after Q. Note that non-focusable activity, in picture-in-picture mode for instance, 701 * does not count as a topmost activity. 702 */ updateTopResumingActivityInProcessIfNeeded(@onNull ActivityRecord activity)703 boolean updateTopResumingActivityInProcessIfNeeded(@NonNull ActivityRecord activity) { 704 if (mInfo.targetSdkVersion >= Q || mPreQTopResumedActivity == activity) { 705 return true; 706 } 707 708 if (!activity.isAttached()) { 709 // No need to update if the activity hasn't attach to any display. 710 return false; 711 } 712 713 boolean canUpdate = false; 714 final DisplayContent topDisplay = 715 (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isAttached()) 716 ? mPreQTopResumedActivity.mDisplayContent 717 : null; 718 // Update the topmost activity if current top activity is 719 // - not on any display OR 720 // - no longer visible OR 721 // - not focusable (in PiP mode for instance) 722 if (topDisplay == null 723 || !mPreQTopResumedActivity.mVisibleRequested 724 || !mPreQTopResumedActivity.isFocusable()) { 725 canUpdate = true; 726 } 727 728 final DisplayContent display = activity.mDisplayContent; 729 // Update the topmost activity if the current top activity wasn't on top of the other one. 730 if (!canUpdate && topDisplay.compareTo(display) < 0) { 731 canUpdate = true; 732 } 733 734 // Update the topmost activity if the activity has higher z-order than the current 735 // top-resumed activity. 736 if (!canUpdate) { 737 final ActivityRecord ar = topDisplay.getActivity(r -> r == activity, 738 true /* traverseTopToBottom */, mPreQTopResumedActivity); 739 if (ar != null && ar != mPreQTopResumedActivity) { 740 canUpdate = true; 741 } 742 } 743 744 if (canUpdate) { 745 // Make sure the previous top activity in the process no longer be resumed. 746 if (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isState(RESUMED)) { 747 final TaskFragment taskFrag = mPreQTopResumedActivity.getTaskFragment(); 748 if (taskFrag != null) { 749 boolean userLeaving = taskFrag.shouldBeVisible(null); 750 taskFrag.startPausing(userLeaving, false /* uiSleeping */, 751 activity, "top-resumed-changed"); 752 } 753 } 754 mPreQTopResumedActivity = activity; 755 } 756 return canUpdate; 757 } 758 stopFreezingActivities()759 public void stopFreezingActivities() { 760 synchronized (mAtm.mGlobalLock) { 761 int i = mActivities.size(); 762 while (i > 0) { 763 i--; 764 mActivities.get(i).stopFreezingScreenLocked(true); 765 } 766 } 767 } 768 finishActivities()769 void finishActivities() { 770 ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities); 771 for (int i = 0; i < activities.size(); i++) { 772 final ActivityRecord r = activities.get(i); 773 if (!r.finishing && r.isInRootTaskLocked()) { 774 r.finishIfPossible("finish-heavy", true /* oomAdj */); 775 } 776 } 777 } 778 isInterestingToUser()779 public boolean isInterestingToUser() { 780 synchronized (mAtm.mGlobalLock) { 781 final int size = mActivities.size(); 782 for (int i = 0; i < size; i++) { 783 ActivityRecord r = mActivities.get(i); 784 if (r.isInterestingToUserLocked()) { 785 return true; 786 } 787 } 788 if (isEmbedded()) { 789 return true; 790 } 791 } 792 return false; 793 } 794 795 /** 796 * @return {@code true} if this process is rendering content on to a window shown by 797 * another process. 798 */ isEmbedded()799 private boolean isEmbedded() { 800 for (int i = mHostActivities.size() - 1; i >= 0; --i) { 801 final ActivityRecord r = mHostActivities.get(i); 802 if (r.isInterestingToUserLocked()) { 803 return true; 804 } 805 } 806 return false; 807 } 808 hasRunningActivity(String packageName)809 public boolean hasRunningActivity(String packageName) { 810 synchronized (mAtm.mGlobalLock) { 811 for (int i = mActivities.size() - 1; i >= 0; --i) { 812 final ActivityRecord r = mActivities.get(i); 813 if (packageName.equals(r.packageName)) { 814 return true; 815 } 816 } 817 } 818 return false; 819 } 820 821 // TODO(b/199277065): Re-assess how app-specific locales are applied based on UXR 822 // TODO(b/199277729): Consider whether we need to add special casing for edge cases like 823 // activity-embeddings etc. updateAppSpecificSettingsForAllActivities(Integer nightMode, LocaleList localesOverride)824 void updateAppSpecificSettingsForAllActivities(Integer nightMode, LocaleList localesOverride) { 825 for (int i = mActivities.size() - 1; i >= 0; --i) { 826 final ActivityRecord r = mActivities.get(i); 827 if (r.applyAppSpecificConfig(nightMode, localesOverride) && r.mVisibleRequested) { 828 r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */); 829 } 830 } 831 } 832 clearPackagePreferredForHomeActivities()833 public void clearPackagePreferredForHomeActivities() { 834 synchronized (mAtm.mGlobalLock) { 835 for (int i = mActivities.size() - 1; i >= 0; --i) { 836 final ActivityRecord r = mActivities.get(i); 837 if (r.isActivityTypeHome()) { 838 Log.i(TAG, "Clearing package preferred activities from " + r.packageName); 839 try { 840 ActivityThread.getPackageManager() 841 .clearPackagePreferredActivities(r.packageName); 842 } catch (RemoteException c) { 843 // pm is in same process, this will never happen. 844 } 845 } 846 } 847 } 848 } 849 hasStartedActivity(ActivityRecord launchedActivity)850 boolean hasStartedActivity(ActivityRecord launchedActivity) { 851 for (int i = mActivities.size() - 1; i >= 0; i--) { 852 final ActivityRecord activity = mActivities.get(i); 853 if (launchedActivity == activity) { 854 continue; 855 } 856 if (!activity.stopped) { 857 return true; 858 } 859 } 860 return false; 861 } 862 hasResumedActivity()863 boolean hasResumedActivity() { 864 return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0; 865 } 866 updateIntentForHeavyWeightActivity(Intent intent)867 void updateIntentForHeavyWeightActivity(Intent intent) { 868 if (mActivities.isEmpty()) { 869 return; 870 } 871 ActivityRecord hist = mActivities.get(0); 872 intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName); 873 intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().mTaskId); 874 } 875 shouldKillProcessForRemovedTask(Task task)876 boolean shouldKillProcessForRemovedTask(Task task) { 877 for (int k = 0; k < mActivities.size(); k++) { 878 final ActivityRecord activity = mActivities.get(k); 879 if (!activity.stopped) { 880 // Don't kill process(es) that has an activity not stopped. 881 return false; 882 } 883 final Task otherTask = activity.getTask(); 884 if (task.mTaskId != otherTask.mTaskId && otherTask.inRecents) { 885 // Don't kill process(es) that has an activity in a different task that is 886 // also in recents. 887 return false; 888 } 889 } 890 return true; 891 } 892 releaseSomeActivities(String reason)893 void releaseSomeActivities(String reason) { 894 // Examine all activities currently running in the process. 895 // Candidate activities that can be destroyed. 896 ArrayList<ActivityRecord> candidates = null; 897 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + this); 898 for (int i = 0; i < mActivities.size(); i++) { 899 final ActivityRecord r = mActivities.get(i); 900 // First, if we find an activity that is in the process of being destroyed, 901 // then we just aren't going to do anything for now; we want things to settle 902 // down before we try to prune more activities. 903 if (r.finishing || r.isState(DESTROYING, DESTROYED)) { 904 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r); 905 return; 906 } 907 // Don't consider any activities that are currently not in a state where they 908 // can be destroyed. 909 if (r.mVisibleRequested || !r.stopped || !r.hasSavedState() || !r.isDestroyable() 910 || r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING)) { 911 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r); 912 continue; 913 } 914 915 if (r.getParent() != null) { 916 if (candidates == null) { 917 candidates = new ArrayList<>(); 918 } 919 candidates.add(r); 920 } 921 } 922 923 if (candidates != null) { 924 // Sort based on z-order in hierarchy. 925 candidates.sort(WindowContainer::compareTo); 926 // Release some older activities 927 int maxRelease = Math.max(candidates.size(), 1); 928 do { 929 final ActivityRecord r = candidates.remove(0); 930 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + r 931 + " in state " + r.getState() + " for reason " + reason); 932 r.destroyImmediately(reason); 933 --maxRelease; 934 } while (maxRelease > 0); 935 } 936 } 937 938 /** 939 * Returns display UI context list which there is any app window shows or starting activities 940 * int this process. 941 */ getDisplayContextsWithErrorDialogs(List<Context> displayContexts)942 public void getDisplayContextsWithErrorDialogs(List<Context> displayContexts) { 943 if (displayContexts == null) { 944 return; 945 } 946 synchronized (mAtm.mGlobalLock) { 947 final RootWindowContainer root = mAtm.mWindowManager.mRoot; 948 root.getDisplayContextsWithNonToastVisibleWindows(mPid, displayContexts); 949 950 for (int i = mActivities.size() - 1; i >= 0; --i) { 951 final ActivityRecord r = mActivities.get(i); 952 final int displayId = r.getDisplayId(); 953 final Context c = root.getDisplayUiContext(displayId); 954 955 if (c != null && r.mVisibleRequested && !displayContexts.contains(c)) { 956 displayContexts.add(c); 957 } 958 } 959 } 960 } 961 962 /** Adds an activity that hosts UI drawn by the current process. */ addHostActivity(ActivityRecord r)963 void addHostActivity(ActivityRecord r) { 964 if (mHostActivities.contains(r)) { 965 return; 966 } 967 mHostActivities.add(r); 968 } 969 970 /** Removes an activity that hosts UI drawn by the current process. */ removeHostActivity(ActivityRecord r)971 void removeHostActivity(ActivityRecord r) { 972 mHostActivities.remove(r); 973 } 974 975 public interface ComputeOomAdjCallback { onVisibleActivity()976 void onVisibleActivity(); onPausedActivity()977 void onPausedActivity(); onStoppingActivity(boolean finishing)978 void onStoppingActivity(boolean finishing); onOtherActivity()979 void onOtherActivity(); 980 } 981 982 /** 983 * Returns the minimum task layer rank. It should only be called if {@link #hasActivities} 984 * returns {@code true}. 985 */ 986 @HotPath(caller = HotPath.OOM_ADJUSTMENT) computeOomAdjFromActivities(ComputeOomAdjCallback callback)987 public int computeOomAdjFromActivities(ComputeOomAdjCallback callback) { 988 final int flags = mActivityStateFlags; 989 if ((flags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) { 990 callback.onVisibleActivity(); 991 } else if ((flags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) { 992 callback.onPausedActivity(); 993 } else if ((flags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) { 994 callback.onStoppingActivity( 995 (flags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0); 996 } else { 997 callback.onOtherActivity(); 998 } 999 return flags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; 1000 } 1001 computeProcessActivityState()1002 void computeProcessActivityState() { 1003 // Since there could be more than one activities in a process record, we don't need to 1004 // compute the OomAdj with each of them, just need to find out the activity with the 1005 // "best" state, the order would be visible, pausing, stopping... 1006 ActivityRecord.State bestInvisibleState = DESTROYED; 1007 boolean allStoppingFinishing = true; 1008 boolean visible = false; 1009 int minTaskLayer = Integer.MAX_VALUE; 1010 int stateFlags = 0; 1011 final boolean wasResumed = hasResumedActivity(); 1012 final boolean wasAnyVisible = (mActivityStateFlags 1013 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0; 1014 for (int i = mActivities.size() - 1; i >= 0; i--) { 1015 final ActivityRecord r = mActivities.get(i); 1016 if (r.isVisible()) { 1017 stateFlags |= ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE; 1018 } 1019 final Task task = r.getTask(); 1020 if (task != null && task.mLayerRank != Task.LAYER_RANK_INVISIBLE) { 1021 stateFlags |= ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK; 1022 } 1023 if (r.mVisibleRequested) { 1024 if (r.isState(RESUMED)) { 1025 stateFlags |= ACTIVITY_STATE_FLAG_HAS_RESUMED; 1026 } 1027 if (task != null && minTaskLayer > 0) { 1028 final int layer = task.mLayerRank; 1029 if (layer >= 0 && minTaskLayer > layer) { 1030 minTaskLayer = layer; 1031 } 1032 } 1033 visible = true; 1034 // continue the loop, in case there are multiple visible activities in 1035 // this process, we'd find out the one with the minimal layer, thus it'll 1036 // get a higher adj score. 1037 } else if (!visible && bestInvisibleState != PAUSING) { 1038 if (r.isState(PAUSING, PAUSED)) { 1039 bestInvisibleState = PAUSING; 1040 } else if (r.isState(STOPPING)) { 1041 bestInvisibleState = STOPPING; 1042 // Not "finishing" if any of activity isn't finishing. 1043 allStoppingFinishing &= r.finishing; 1044 } 1045 } 1046 } 1047 1048 stateFlags |= minTaskLayer & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; 1049 if (visible) { 1050 stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE; 1051 } else if (bestInvisibleState == PAUSING) { 1052 stateFlags |= ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED; 1053 } else if (bestInvisibleState == STOPPING) { 1054 stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING; 1055 if (allStoppingFinishing) { 1056 stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING; 1057 } 1058 } 1059 mActivityStateFlags = stateFlags; 1060 1061 final boolean anyVisible = (stateFlags 1062 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0; 1063 if (!wasAnyVisible && anyVisible) { 1064 mAtm.mVisibleActivityProcessTracker.onAnyActivityVisible(this); 1065 } else if (wasAnyVisible && !anyVisible) { 1066 mAtm.mVisibleActivityProcessTracker.onAllActivitiesInvisible(this); 1067 } else if (wasAnyVisible && !wasResumed && hasResumedActivity()) { 1068 mAtm.mVisibleActivityProcessTracker.onActivityResumedWhileVisible(this); 1069 } 1070 } 1071 1072 /** Called when the process has some oom related changes and it is going to update oom-adj. */ prepareOomAdjustment()1073 private void prepareOomAdjustment() { 1074 mAtm.mRootWindowContainer.rankTaskLayers(); 1075 mAtm.mTaskSupervisor.computeProcessActivityStateBatch(); 1076 } 1077 computeRelaunchReason()1078 public int computeRelaunchReason() { 1079 synchronized (mAtm.mGlobalLock) { 1080 final int activitiesSize = mActivities.size(); 1081 for (int i = activitiesSize - 1; i >= 0; i--) { 1082 final ActivityRecord r = mActivities.get(i); 1083 if (r.mRelaunchReason != RELAUNCH_REASON_NONE) { 1084 return r.mRelaunchReason; 1085 } 1086 } 1087 } 1088 return RELAUNCH_REASON_NONE; 1089 } 1090 1091 /** 1092 * Get the current dispatching timeout. If instrumentation is currently taking place, return 1093 * a longer value. Shorter timeout is returned otherwise. 1094 * @return The timeout in milliseconds 1095 */ getInputDispatchingTimeoutMillis()1096 public long getInputDispatchingTimeoutMillis() { 1097 synchronized (mAtm.mGlobalLock) { 1098 return isInstrumenting() || isUsingWrapper() 1099 ? INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS : 1100 DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 1101 } 1102 } 1103 clearProfilerIfNeeded()1104 void clearProfilerIfNeeded() { 1105 // Posting on handler so WM lock isn't held when we call into AM. 1106 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1107 WindowProcessListener::clearProfilerIfNeeded, mListener)); 1108 } 1109 updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, boolean updateOomAdj, boolean addPendingTopUid)1110 void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, 1111 boolean updateOomAdj, boolean addPendingTopUid) { 1112 if (addPendingTopUid) { 1113 addToPendingTop(); 1114 } 1115 if (updateOomAdj) { 1116 prepareOomAdjustment(); 1117 } 1118 // Posting on handler so WM lock isn't held when we call into AM. 1119 final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo, 1120 mListener, updateServiceConnectionActivities, activityChange, updateOomAdj); 1121 mAtm.mH.sendMessage(m); 1122 } 1123 1124 /** Makes the process have top state before oom-adj is computed from a posted message. */ addToPendingTop()1125 void addToPendingTop() { 1126 mAtm.mAmInternal.addPendingTopUid(mUid, mPid); 1127 } 1128 updateServiceConnectionActivities()1129 void updateServiceConnectionActivities() { 1130 // Posting on handler so WM lock isn't held when we call into AM. 1131 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1132 WindowProcessListener::updateServiceConnectionActivities, mListener)); 1133 } 1134 setPendingUiCleanAndForceProcessStateUpTo(int newState)1135 void setPendingUiCleanAndForceProcessStateUpTo(int newState) { 1136 // Posting on handler so WM lock isn't held when we call into AM. 1137 final Message m = PooledLambda.obtainMessage( 1138 WindowProcessListener::setPendingUiCleanAndForceProcessStateUpTo, 1139 mListener, newState); 1140 mAtm.mH.sendMessage(m); 1141 } 1142 isRemoved()1143 boolean isRemoved() { 1144 return mListener.isRemoved(); 1145 } 1146 shouldSetProfileProc()1147 private boolean shouldSetProfileProc() { 1148 return mAtm.mProfileApp != null && mAtm.mProfileApp.equals(mName) 1149 && (mAtm.mProfileProc == null || mAtm.mProfileProc == this); 1150 } 1151 createProfilerInfoIfNeeded()1152 ProfilerInfo createProfilerInfoIfNeeded() { 1153 final ProfilerInfo currentProfilerInfo = mAtm.mProfilerInfo; 1154 if (currentProfilerInfo == null || currentProfilerInfo.profileFile == null 1155 || !shouldSetProfileProc()) { 1156 return null; 1157 } 1158 if (currentProfilerInfo.profileFd != null) { 1159 try { 1160 currentProfilerInfo.profileFd = currentProfilerInfo.profileFd.dup(); 1161 } catch (IOException e) { 1162 currentProfilerInfo.closeFd(); 1163 } 1164 } 1165 return new ProfilerInfo(currentProfilerInfo); 1166 } 1167 onStartActivity(int topProcessState, ActivityInfo info)1168 void onStartActivity(int topProcessState, ActivityInfo info) { 1169 String packageName = null; 1170 if ((info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0 1171 || !"android".equals(info.packageName)) { 1172 // Don't add this if it is a platform component that is marked to run in multiple 1173 // processes, because this is actually part of the framework so doesn't make sense 1174 // to track as a separate apk in the process. 1175 packageName = info.packageName; 1176 } 1177 // update ActivityManagerService.PendingStartActivityUids list. 1178 if (topProcessState == ActivityManager.PROCESS_STATE_TOP) { 1179 mAtm.mAmInternal.addPendingTopUid(mUid, mPid); 1180 } 1181 prepareOomAdjustment(); 1182 // Posting the message at the front of queue so WM lock isn't held when we call into AM, 1183 // and the process state of starting activity can be updated quicker which will give it a 1184 // higher scheduling group. 1185 final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity, 1186 mListener, topProcessState, shouldSetProfileProc(), packageName, 1187 info.applicationInfo.longVersionCode); 1188 mAtm.mH.sendMessageAtFrontOfQueue(m); 1189 } 1190 appDied(String reason)1191 void appDied(String reason) { 1192 // Posting on handler so WM lock isn't held when we call into AM. 1193 final Message m = PooledLambda.obtainMessage( 1194 WindowProcessListener::appDied, mListener, reason); 1195 mAtm.mH.sendMessage(m); 1196 } 1197 1198 /** 1199 * Clean up the activities belonging to this process. 1200 * 1201 * @return {@code true} if the process has any visible activity. 1202 */ handleAppDied()1203 boolean handleAppDied() { 1204 mAtm.mTaskSupervisor.removeHistoryRecords(this); 1205 1206 boolean hasVisibleActivities = false; 1207 final boolean hasInactiveActivities = 1208 mInactiveActivities != null && !mInactiveActivities.isEmpty(); 1209 final ArrayList<ActivityRecord> activities = 1210 (mHasActivities || hasInactiveActivities) ? new ArrayList<>() : mActivities; 1211 if (mHasActivities) { 1212 activities.addAll(mActivities); 1213 } 1214 if (hasInactiveActivities) { 1215 // Make sure that all activities in this process are handled. 1216 activities.addAll(mInactiveActivities); 1217 } 1218 if (isRemoved()) { 1219 // The package of the died process should be force-stopped, so make its activities as 1220 // finishing to prevent the process from being started again if the next top (or being 1221 // visible) activity also resides in the same process. This must be done before removal. 1222 for (int i = activities.size() - 1; i >= 0; i--) { 1223 activities.get(i).makeFinishingLocked(); 1224 } 1225 } 1226 for (int i = activities.size() - 1; i >= 0; i--) { 1227 final ActivityRecord r = activities.get(i); 1228 if (r.mVisibleRequested || r.isVisible()) { 1229 // While an activity launches a new activity, it's possible that the old activity 1230 // is already requested to be hidden (mVisibleRequested=false), but this visibility 1231 // is not yet committed, so isVisible()=true. 1232 hasVisibleActivities = true; 1233 } 1234 1235 final TaskFragment taskFragment = r.getTaskFragment(); 1236 if (taskFragment != null) { 1237 // There may be a pausing activity that hasn't shown any window and was requested 1238 // to be hidden. But pausing is also a visible state, it should be regarded as 1239 // visible, so the caller can know the next activity should be resumed. 1240 hasVisibleActivities |= taskFragment.handleAppDied(this); 1241 } 1242 r.handleAppDied(); 1243 } 1244 clearRecentTasks(); 1245 clearActivities(); 1246 1247 return hasVisibleActivities; 1248 } 1249 registerDisplayAreaConfigurationListener(@ullable DisplayArea displayArea)1250 void registerDisplayAreaConfigurationListener(@Nullable DisplayArea displayArea) { 1251 if (displayArea == null || displayArea.containsListener(this)) { 1252 return; 1253 } 1254 unregisterConfigurationListeners(); 1255 mDisplayArea = displayArea; 1256 displayArea.registerConfigurationChangeListener(this); 1257 } 1258 1259 @VisibleForTesting unregisterDisplayAreaConfigurationListener()1260 void unregisterDisplayAreaConfigurationListener() { 1261 if (mDisplayArea == null) { 1262 return; 1263 } 1264 mDisplayArea.unregisterConfigurationChangeListener(this); 1265 mDisplayArea = null; 1266 onMergedOverrideConfigurationChanged(Configuration.EMPTY); 1267 } 1268 registerActivityConfigurationListener(ActivityRecord activityRecord)1269 void registerActivityConfigurationListener(ActivityRecord activityRecord) { 1270 if (activityRecord == null || activityRecord.containsListener(this) 1271 // Check for the caller from outside of this class. 1272 || !mIsActivityConfigOverrideAllowed) { 1273 return; 1274 } 1275 unregisterConfigurationListeners(); 1276 mConfigActivityRecord = activityRecord; 1277 activityRecord.registerConfigurationChangeListener(this); 1278 } 1279 unregisterActivityConfigurationListener()1280 private void unregisterActivityConfigurationListener() { 1281 if (mConfigActivityRecord == null) { 1282 return; 1283 } 1284 mConfigActivityRecord.unregisterConfigurationChangeListener(this); 1285 mConfigActivityRecord = null; 1286 onMergedOverrideConfigurationChanged(Configuration.EMPTY); 1287 } 1288 1289 /** 1290 * A process can only register to one {@link WindowContainer} to listen to the override 1291 * configuration changes. Unregisters the existing listener if it has one before registers a 1292 * new one. 1293 */ unregisterConfigurationListeners()1294 private void unregisterConfigurationListeners() { 1295 unregisterActivityConfigurationListener(); 1296 unregisterDisplayAreaConfigurationListener(); 1297 } 1298 1299 /** 1300 * Check if activity configuration override for the activity process needs an update and perform 1301 * if needed. By default we try to override the process configuration to match the top activity 1302 * config to increase app compatibility with multi-window and multi-display. The process will 1303 * always track the configuration of the non-finishing activity last added to the process. 1304 */ updateActivityConfigurationListener()1305 private void updateActivityConfigurationListener() { 1306 if (!mIsActivityConfigOverrideAllowed) { 1307 return; 1308 } 1309 1310 for (int i = mActivities.size() - 1; i >= 0; i--) { 1311 final ActivityRecord activityRecord = mActivities.get(i); 1312 if (!activityRecord.finishing) { 1313 // Eligible activity is found, update listener. 1314 registerActivityConfigurationListener(activityRecord); 1315 return; 1316 } 1317 } 1318 1319 // No eligible activities found, let's remove the configuration listener. 1320 unregisterActivityConfigurationListener(); 1321 } 1322 1323 @Override onConfigurationChanged(Configuration newGlobalConfig)1324 public void onConfigurationChanged(Configuration newGlobalConfig) { 1325 super.onConfigurationChanged(newGlobalConfig); 1326 updateConfiguration(); 1327 } 1328 1329 @Override onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration)1330 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) { 1331 super.onRequestedOverrideConfigurationChanged(overrideConfiguration); 1332 } 1333 1334 @Override onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig)1335 public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) { 1336 super.onRequestedOverrideConfigurationChanged(mergedOverrideConfig); 1337 } 1338 1339 @Override resolveOverrideConfiguration(Configuration newParentConfig)1340 void resolveOverrideConfiguration(Configuration newParentConfig) { 1341 final Configuration requestedOverrideConfig = getRequestedOverrideConfiguration(); 1342 if (requestedOverrideConfig.assetsSeq != ASSETS_SEQ_UNDEFINED 1343 && newParentConfig.assetsSeq > requestedOverrideConfig.assetsSeq) { 1344 requestedOverrideConfig.assetsSeq = ASSETS_SEQ_UNDEFINED; 1345 } 1346 super.resolveOverrideConfiguration(newParentConfig); 1347 final Configuration resolvedConfig = getResolvedOverrideConfiguration(); 1348 // Make sure that we don't accidentally override the activity type. 1349 resolvedConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); 1350 // Activity has an independent ActivityRecord#mConfigurationSeq. If this process registers 1351 // activity configuration, its config seq shouldn't go backwards by activity configuration. 1352 // Otherwise if other places send wpc.getConfiguration() to client, the configuration may 1353 // be ignored due to the seq is older. 1354 resolvedConfig.seq = newParentConfig.seq; 1355 } 1356 updateConfiguration()1357 private void updateConfiguration() { 1358 final Configuration config = getConfiguration(); 1359 if (mLastReportedConfiguration.diff(config) == 0) { 1360 // Nothing changed. 1361 if (Build.IS_DEBUGGABLE && mHasImeService) { 1362 // TODO (b/135719017): Temporary log for debugging IME service. 1363 Slog.w(TAG_CONFIGURATION, "Current config: " + config 1364 + " unchanged for IME proc " + mName); 1365 } 1366 return; 1367 } 1368 1369 if (mPauseConfigurationDispatchCount > 0) { 1370 mHasPendingConfigurationChange = true; 1371 return; 1372 } 1373 dispatchConfiguration(config); 1374 } 1375 dispatchConfiguration(Configuration config)1376 void dispatchConfiguration(Configuration config) { 1377 mHasPendingConfigurationChange = false; 1378 if (mThread == null) { 1379 if (Build.IS_DEBUGGABLE && mHasImeService) { 1380 // TODO (b/135719017): Temporary log for debugging IME service. 1381 Slog.w(TAG_CONFIGURATION, "Unable to send config for IME proc " + mName 1382 + ": no app thread"); 1383 } 1384 return; 1385 } 1386 ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName, 1387 config); 1388 if (Build.IS_DEBUGGABLE && mHasImeService) { 1389 // TODO (b/135719017): Temporary log for debugging IME service. 1390 Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config); 1391 } 1392 1393 try { 1394 config.seq = mAtm.increaseConfigurationSeqLocked(); 1395 mAtm.getLifecycleManager().scheduleTransaction(mThread, 1396 ConfigurationChangeItem.obtain(config)); 1397 setLastReportedConfiguration(config); 1398 } catch (Exception e) { 1399 Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change", e); 1400 } 1401 } 1402 setLastReportedConfiguration(Configuration config)1403 void setLastReportedConfiguration(Configuration config) { 1404 mLastReportedConfiguration.setTo(config); 1405 } 1406 getLastReportedConfiguration()1407 Configuration getLastReportedConfiguration() { 1408 return mLastReportedConfiguration; 1409 } 1410 pauseConfigurationDispatch()1411 void pauseConfigurationDispatch() { 1412 mPauseConfigurationDispatchCount++; 1413 } 1414 1415 /** Returns {@code true} if the configuration change is pending to dispatch. */ resumeConfigurationDispatch()1416 boolean resumeConfigurationDispatch() { 1417 if (mPauseConfigurationDispatchCount == 0) { 1418 return false; 1419 } 1420 mPauseConfigurationDispatchCount--; 1421 return mHasPendingConfigurationChange; 1422 } 1423 updateAssetConfiguration(int assetSeq)1424 void updateAssetConfiguration(int assetSeq) { 1425 // Update the process override configuration directly if the process configuration will 1426 // not be override from its activities. 1427 if (!mHasActivities || !mIsActivityConfigOverrideAllowed) { 1428 Configuration overrideConfig = new Configuration(getRequestedOverrideConfiguration()); 1429 overrideConfig.assetsSeq = assetSeq; 1430 onRequestedOverrideConfigurationChanged(overrideConfig); 1431 return; 1432 } 1433 1434 // Otherwise, we can just update the activity override configuration. 1435 for (int i = mActivities.size() - 1; i >= 0; i--) { 1436 ActivityRecord r = mActivities.get(i); 1437 Configuration overrideConfig = new Configuration(r.getRequestedOverrideConfiguration()); 1438 overrideConfig.assetsSeq = assetSeq; 1439 r.onRequestedOverrideConfigurationChanged(overrideConfig); 1440 if (r.mVisibleRequested) { 1441 r.ensureActivityConfiguration(0, true); 1442 } 1443 } 1444 } 1445 1446 /** 1447 * This is called for sending {@link android.app.servertransaction.LaunchActivityItem}. 1448 * The caller must call {@link #setLastReportedConfiguration} if the delivered configuration 1449 * is newer. 1450 */ prepareConfigurationForLaunchingActivity()1451 Configuration prepareConfigurationForLaunchingActivity() { 1452 final Configuration config = getConfiguration(); 1453 if (mHasPendingConfigurationChange) { 1454 mHasPendingConfigurationChange = false; 1455 // The global configuration may not change, so the client process may have the same 1456 // config seq. This increment ensures that the client won't ignore the configuration. 1457 config.seq = mAtm.increaseConfigurationSeqLocked(); 1458 } 1459 return config; 1460 } 1461 1462 /** Returns the total time (in milliseconds) spent executing in both user and system code. */ getCpuTime()1463 public long getCpuTime() { 1464 return mListener.getCpuTime(); 1465 } 1466 addRecentTask(Task task)1467 void addRecentTask(Task task) { 1468 mRecentTasks.add(task); 1469 mHasRecentTasks = true; 1470 } 1471 removeRecentTask(Task task)1472 void removeRecentTask(Task task) { 1473 mRecentTasks.remove(task); 1474 mHasRecentTasks = !mRecentTasks.isEmpty(); 1475 } 1476 1477 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasRecentTasks()1478 public boolean hasRecentTasks() { 1479 return mHasRecentTasks; 1480 } 1481 clearRecentTasks()1482 void clearRecentTasks() { 1483 for (int i = mRecentTasks.size() - 1; i >= 0; i--) { 1484 mRecentTasks.get(i).clearRootProcess(); 1485 } 1486 mRecentTasks.clear(); 1487 mHasRecentTasks = false; 1488 } 1489 appEarlyNotResponding(String annotation, Runnable killAppCallback)1490 public void appEarlyNotResponding(String annotation, Runnable killAppCallback) { 1491 Runnable targetRunnable = null; 1492 synchronized (mAtm.mGlobalLock) { 1493 if (mAtm.mController == null) { 1494 return; 1495 } 1496 1497 try { 1498 // 0 == continue, -1 = kill process immediately 1499 int res = mAtm.mController.appEarlyNotResponding(mName, mPid, annotation); 1500 if (res < 0 && mPid != MY_PID) { 1501 targetRunnable = killAppCallback; 1502 } 1503 } catch (RemoteException e) { 1504 mAtm.mController = null; 1505 Watchdog.getInstance().setActivityController(null); 1506 } 1507 } 1508 if (targetRunnable != null) { 1509 targetRunnable.run(); 1510 } 1511 } 1512 appNotResponding(String info, Runnable killAppCallback, Runnable serviceTimeoutCallback)1513 public boolean appNotResponding(String info, Runnable killAppCallback, 1514 Runnable serviceTimeoutCallback) { 1515 Runnable targetRunnable = null; 1516 synchronized (mAtm.mGlobalLock) { 1517 if (mAtm.mController == null) { 1518 return false; 1519 } 1520 1521 try { 1522 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately 1523 int res = mAtm.mController.appNotResponding(mName, mPid, info); 1524 if (res != 0) { 1525 if (res < 0 && mPid != MY_PID) { 1526 targetRunnable = killAppCallback; 1527 } else { 1528 targetRunnable = serviceTimeoutCallback; 1529 } 1530 } 1531 } catch (RemoteException e) { 1532 mAtm.mController = null; 1533 Watchdog.getInstance().setActivityController(null); 1534 return false; 1535 } 1536 } 1537 if (targetRunnable != null) { 1538 // Execute runnable outside WM lock since the runnable will hold AM lock 1539 targetRunnable.run(); 1540 return true; 1541 } 1542 return false; 1543 } 1544 1545 /** 1546 * Called to notify {@link WindowProcessController} of a started service. 1547 * 1548 * @param serviceInfo information describing the started service. 1549 */ onServiceStarted(ServiceInfo serviceInfo)1550 public void onServiceStarted(ServiceInfo serviceInfo) { 1551 String permission = serviceInfo.permission; 1552 if (permission == null) { 1553 return; 1554 } 1555 1556 // TODO: Audit remaining services for disabling activity override (Wallpaper, Dream, etc). 1557 switch (permission) { 1558 case Manifest.permission.BIND_INPUT_METHOD: 1559 mHasImeService = true; 1560 // Fall-through 1561 case Manifest.permission.BIND_ACCESSIBILITY_SERVICE: 1562 case Manifest.permission.BIND_VOICE_INTERACTION: 1563 // We want to avoid overriding the config of these services with that of the 1564 // activity as it could lead to incorrect display metrics. For ex, IME services 1565 // expect their config to match the config of the display with the IME window 1566 // showing. 1567 // If the configuration has been overridden by previous activity, empty it. 1568 mIsActivityConfigOverrideAllowed = false; 1569 unregisterActivityConfigurationListener(); 1570 break; 1571 default: 1572 break; 1573 } 1574 } 1575 1576 @HotPath(caller = HotPath.OOM_ADJUSTMENT) onTopProcChanged()1577 public void onTopProcChanged() { 1578 if (mAtm.mVrController.isInterestingToSchedGroup()) { 1579 mAtm.mH.post(() -> { 1580 synchronized (mAtm.mGlobalLock) { 1581 mAtm.mVrController.onTopProcChangedLocked(this); 1582 } 1583 }); 1584 } 1585 } 1586 1587 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isHomeProcess()1588 public boolean isHomeProcess() { 1589 return this == mAtm.mHomeProcess; 1590 } 1591 1592 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isPreviousProcess()1593 public boolean isPreviousProcess() { 1594 return this == mAtm.mPreviousProcess; 1595 } 1596 1597 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isHeavyWeightProcess()1598 public boolean isHeavyWeightProcess() { 1599 return this == mAtm.mHeavyWeightProcess; 1600 } 1601 setRunningRecentsAnimation(boolean running)1602 void setRunningRecentsAnimation(boolean running) { 1603 if (mRunningRecentsAnimation == running) { 1604 return; 1605 } 1606 mRunningRecentsAnimation = running; 1607 updateRunningRemoteOrRecentsAnimation(); 1608 } 1609 setRunningRemoteAnimation(boolean running)1610 void setRunningRemoteAnimation(boolean running) { 1611 if (mRunningRemoteAnimation == running) { 1612 return; 1613 } 1614 mRunningRemoteAnimation = running; 1615 updateRunningRemoteOrRecentsAnimation(); 1616 } 1617 1618 /** 1619 * Marks another process as a "delegate" animator. This means that process is doing some part 1620 * of a remote animation on behalf of this process. 1621 */ addRemoteAnimationDelegate(WindowProcessController delegate)1622 void addRemoteAnimationDelegate(WindowProcessController delegate) { 1623 if (!isRunningRemoteTransition()) { 1624 throw new IllegalStateException("Can't add a delegate to a process which isn't itself" 1625 + " running a remote animation"); 1626 } 1627 mRemoteAnimationDelegates.add(new WeakReference<>(delegate)); 1628 } 1629 updateRunningRemoteOrRecentsAnimation()1630 void updateRunningRemoteOrRecentsAnimation() { 1631 if (!isRunningRemoteTransition()) { 1632 // Clean-up any delegates 1633 for (int i = 0; i < mRemoteAnimationDelegates.size(); ++i) { 1634 final WindowProcessController delegate = mRemoteAnimationDelegates.get(i).get(); 1635 if (delegate == null) continue; 1636 delegate.setRunningRemoteAnimation(false); 1637 delegate.setRunningRecentsAnimation(false); 1638 } 1639 mRemoteAnimationDelegates.clear(); 1640 } 1641 1642 // Posting on handler so WM lock isn't held when we call into AM. 1643 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1644 WindowProcessListener::setRunningRemoteAnimation, mListener, 1645 isRunningRemoteTransition())); 1646 } 1647 isRunningRemoteTransition()1648 boolean isRunningRemoteTransition() { 1649 return mRunningRecentsAnimation || mRunningRemoteAnimation; 1650 } 1651 1652 /** Adjusts scheduling group for animation. This method MUST NOT be called inside WM lock. */ setRunningAnimationUnsafe()1653 void setRunningAnimationUnsafe() { 1654 mListener.setRunningRemoteAnimation(true); 1655 } 1656 1657 @Override toString()1658 public String toString() { 1659 return mOwner != null ? mOwner.toString() : null; 1660 } 1661 dump(PrintWriter pw, String prefix)1662 public void dump(PrintWriter pw, String prefix) { 1663 synchronized (mAtm.mGlobalLock) { 1664 if (mActivities.size() > 0) { 1665 pw.print(prefix); pw.println("Activities:"); 1666 for (int i = 0; i < mActivities.size(); i++) { 1667 pw.print(prefix); pw.print(" - "); pw.println(mActivities.get(i)); 1668 } 1669 } 1670 1671 if (mRecentTasks.size() > 0) { 1672 pw.println(prefix + "Recent Tasks:"); 1673 for (int i = 0; i < mRecentTasks.size(); i++) { 1674 pw.println(prefix + " - " + mRecentTasks.get(i)); 1675 } 1676 } 1677 1678 if (mVrThreadTid != 0) { 1679 pw.print(prefix); pw.print("mVrThreadTid="); pw.println(mVrThreadTid); 1680 } 1681 1682 mBgLaunchController.dump(pw, prefix); 1683 } 1684 pw.println(prefix + " Configuration=" + getConfiguration()); 1685 pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration()); 1686 pw.println(prefix + " mLastReportedConfiguration=" + mLastReportedConfiguration); 1687 1688 final int stateFlags = mActivityStateFlags; 1689 if (stateFlags != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) { 1690 pw.print(prefix + " mActivityStateFlags="); 1691 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE) != 0) { 1692 pw.print("W|"); 1693 } 1694 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) { 1695 pw.print("V|"); 1696 if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0) { 1697 pw.print("R|"); 1698 } 1699 } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) { 1700 pw.print("P|"); 1701 } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) { 1702 pw.print("S|"); 1703 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0) { 1704 pw.print("F|"); 1705 } 1706 } 1707 final int taskLayer = stateFlags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; 1708 if (taskLayer != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) { 1709 pw.print("taskLayer=" + taskLayer); 1710 } 1711 pw.println(); 1712 } 1713 } 1714 dumpDebug(ProtoOutputStream proto, long fieldId)1715 void dumpDebug(ProtoOutputStream proto, long fieldId) { 1716 mListener.dumpDebug(proto, fieldId); 1717 } 1718 } 1719