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_CACHED_ACTIVITY; 20 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 23 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 24 import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED; 25 import static android.os.Build.VERSION_CODES.Q; 26 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 27 import static android.view.WindowManager.TRANSIT_CLOSE; 28 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED; 29 30 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_CONFIGURATION; 31 import static com.android.internal.util.Preconditions.checkArgument; 32 import static com.android.server.am.ProcessList.INVALID_ADJ; 33 import static com.android.server.wm.ActivityRecord.State.DESTROYED; 34 import static com.android.server.wm.ActivityRecord.State.DESTROYING; 35 import static com.android.server.wm.ActivityRecord.State.PAUSED; 36 import static com.android.server.wm.ActivityRecord.State.PAUSING; 37 import static com.android.server.wm.ActivityRecord.State.RESUMED; 38 import static com.android.server.wm.ActivityRecord.State.STARTED; 39 import static com.android.server.wm.ActivityRecord.State.STOPPED; 40 import static com.android.server.wm.ActivityRecord.State.STOPPING; 41 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; 42 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; 43 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; 44 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 45 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 46 import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS; 47 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; 48 import static com.android.server.wm.WindowManagerService.MY_PID; 49 50 import static java.util.Objects.requireNonNull; 51 52 import android.Manifest; 53 import android.annotation.IntDef; 54 import android.annotation.NonNull; 55 import android.annotation.Nullable; 56 import android.app.ActivityManager; 57 import android.app.ActivityThread; 58 import android.app.BackgroundStartPrivileges; 59 import android.app.IApplicationThread; 60 import android.app.ProfilerInfo; 61 import android.app.servertransaction.ClientTransactionItem; 62 import android.app.servertransaction.ConfigurationChangeItem; 63 import android.content.ComponentName; 64 import android.content.Context; 65 import android.content.Intent; 66 import android.content.pm.ActivityInfo; 67 import android.content.pm.ApplicationInfo; 68 import android.content.pm.ServiceInfo; 69 import android.content.res.Configuration; 70 import android.os.Binder; 71 import android.os.Build; 72 import android.os.FactoryTest; 73 import android.os.LocaleList; 74 import android.os.Message; 75 import android.os.Process; 76 import android.os.RemoteException; 77 import android.os.SystemProperties; 78 import android.os.UserHandle; 79 import android.util.ArrayMap; 80 import android.util.Log; 81 import android.util.Slog; 82 import android.util.proto.ProtoOutputStream; 83 84 import com.android.internal.annotations.GuardedBy; 85 import com.android.internal.annotations.VisibleForTesting; 86 import com.android.internal.app.HeavyWeightSwitcherActivity; 87 import com.android.internal.protolog.ProtoLog; 88 import com.android.internal.util.function.pooled.PooledLambda; 89 import com.android.server.Watchdog; 90 import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal; 91 import com.android.server.wm.ActivityTaskManagerService.HotPath; 92 import com.android.server.wm.BackgroundLaunchProcessController.BalCheckConfiguration; 93 94 import java.io.IOException; 95 import java.io.PrintWriter; 96 import java.lang.annotation.Retention; 97 import java.lang.annotation.RetentionPolicy; 98 import java.util.ArrayList; 99 import java.util.List; 100 101 /** 102 * The Activity Manager (AM) package manages the lifecycle of processes in the system through 103 * ProcessRecord. However, it is important for the Window Manager (WM) package to be aware 104 * of the processes and their state since it affects how WM manages windows and activities. This 105 * class that allows the ProcessRecord object in the AM package to communicate important 106 * changes to its state to the WM package in a structured way. WM package also uses 107 * {@link WindowProcessListener} to request changes to the process state on the AM side. 108 * Note that public calls into this class are assumed to be originating from outside the 109 * window manager so the window manager lock is held and appropriate permissions are checked before 110 * calls are allowed to proceed. 111 */ 112 public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer> 113 implements ConfigurationContainerListener { 114 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM; 115 private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; 116 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; 117 118 /** 119 * The max number of processes which can be top scheduling group if there are non-top visible 120 * freeform activities run in the process. 121 */ 122 private static final int MAX_NUM_PERCEPTIBLE_FREEFORM = 123 SystemProperties.getInt("persist.wm.max_num_perceptible_freeform", 1); 124 /** 125 * If the visible area percentage of a resumed freeform task is greater than or equal to this 126 * ratio, its process will have a higher priority. 127 */ 128 private static final int PERCEPTIBLE_FREEFORM_VISIBLE_RATIO = 90; 129 130 private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 200; 131 private static final long RAPID_ACTIVITY_LAUNCH_MS = 500; 132 private static final long RESET_RAPID_ACTIVITY_LAUNCH_MS = 3 * RAPID_ACTIVITY_LAUNCH_MS; 133 134 public static final int STOPPED_STATE_NOT_STOPPED = 0; 135 public static final int STOPPED_STATE_FIRST_LAUNCH = 1; 136 public static final int STOPPED_STATE_FORCE_STOPPED = 2; 137 138 private int mRapidActivityLaunchCount; 139 140 // all about the first app in the process 141 volatile ApplicationInfo mInfo; 142 final String mName; 143 final int mUid; 144 145 // The process of this application; 0 if none 146 private volatile int mPid; 147 // user of process. 148 final int mUserId; 149 // The owner of this window process controller object. Mainly for identification when we 150 // communicate back to the activity manager side. 151 public final Object mOwner; 152 // List of packages running in the process 153 @GuardedBy("itself") 154 private final ArrayList<String> mPkgList = new ArrayList<>(1); 155 private final WindowProcessListener mListener; 156 private final ActivityTaskManagerService mAtm; 157 private final BackgroundLaunchProcessController mBgLaunchController; 158 // The actual proc... may be null only if 'persistent' is true (in which case we are in the 159 // process of launching the app) 160 private IApplicationThread mThread; 161 // Currently desired scheduling class 162 private volatile int mCurSchedGroup; 163 // Currently computed process state 164 private volatile int mCurProcState = PROCESS_STATE_NONEXISTENT; 165 // Last reported process state; 166 private volatile int mRepProcState = PROCESS_STATE_NONEXISTENT; 167 // Currently computed oom adj score 168 private volatile int mCurAdj = INVALID_ADJ; 169 // are we in the process of crashing? 170 private volatile boolean mCrashing; 171 // does the app have a not responding dialog? 172 private volatile boolean mNotResponding; 173 // always keep this application running? 174 private volatile boolean mPersistent; 175 // The ABI this process was launched with 176 private volatile String mRequiredAbi; 177 // Running any services that are foreground? 178 private volatile boolean mHasForegroundServices; 179 // Are there any client services with activities? 180 private volatile boolean mHasClientActivities; 181 // Is this process currently showing a non-activity UI that the user is interacting with? 182 // E.g. The status bar when it is expanded, but not when it is minimized. When true the process 183 // will be set to use the ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost performance. 184 private volatile boolean mHasTopUi; 185 // Is the process currently showing a non-activity UI that overlays on-top of activity UIs on 186 // screen. E.g. display a window of type 187 // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY When true the process will 188 // oom adj score will be set to ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance 189 // of the process getting killed. 190 private volatile boolean mHasOverlayUi; 191 // Want to clean up resources from showing UI? 192 private volatile boolean mPendingUiClean; 193 // The time we sent the last interaction event 194 private volatile long mInteractionEventTime; 195 // When we became foreground for interaction purposes 196 private volatile long mFgInteractionTime; 197 // When (uptime) the process last became unimportant 198 private volatile long mWhenUnimportant; 199 // was app launched for debugging? 200 private volatile boolean mDebugging; 201 // Active instrumentation running in process? 202 private volatile boolean mInstrumenting; 203 // If there is active instrumentation, this is the source 204 private volatile int mInstrumentationSourceUid = -1; 205 // Active instrumentation with background activity starts privilege running in process? 206 private volatile boolean mInstrumentingWithBackgroundActivityStartPrivileges; 207 // This process it perceptible by the user. 208 private volatile boolean mPerceptible; 209 // Set to true when process was launched with a wrapper attached 210 private volatile boolean mUsingWrapper; 211 212 /** Whether this process has ever completed ActivityThread#handleBindApplication. */ 213 boolean mHasEverAttached; 214 215 /** Non-null if this process may have a window. */ 216 @Nullable 217 Session mWindowSession; 218 219 // Thread currently set for VR scheduling 220 int mVrThreadTid; 221 222 // Whether this process has ever started a service with the BIND_INPUT_METHOD permission. 223 private volatile boolean mHasImeService; 224 225 /** 226 * Whether this process can use realtime prioirity (SCHED_FIFO) for its UI and render threads 227 * when this process is SCHED_GROUP_TOP_APP. 228 */ 229 private final boolean mUseFifoUiScheduling; 230 231 /** Whether {@link #mActivities} is not empty. */ 232 private volatile boolean mHasActivities; 233 /** All activities running in the process (exclude destroying). */ 234 private final ArrayList<ActivityRecord> mActivities = new ArrayList<>(); 235 /** The activities will be removed but still belong to this process. */ 236 private ArrayList<ActivityRecord> mInactiveActivities; 237 /** Whether {@link #mRecentTasks} is not empty. */ 238 private volatile boolean mHasRecentTasks; 239 // any tasks this process had run root activities in 240 private final ArrayList<Task> mRecentTasks = new ArrayList<>(); 241 // The most recent top-most activity that was resumed in the process for pre-Q app. 242 private ActivityRecord mPreQTopResumedActivity = null; 243 // The last time an activity was launched in the process 244 private volatile long mLastActivityLaunchTime; 245 // The last time an activity was finished in the process while the process participated 246 // in a visible task 247 private volatile long mLastActivityFinishTime; 248 249 // Last configuration that was reported to the process. 250 private final Configuration mLastReportedConfiguration = new Configuration(); 251 /** Whether the process configuration is waiting to be dispatched to the process. */ 252 private boolean mHasPendingConfigurationChange; 253 254 /** If the process state is in (<=) the cached state, then defer delivery of the config. */ 255 private static final int CACHED_CONFIG_PROC_STATE = PROCESS_STATE_CACHED_ACTIVITY; 256 /** Whether {@link #mLastReportedConfiguration} is deferred by the cached state. */ 257 private volatile boolean mHasCachedConfiguration; 258 259 private int mLastTopActivityDeviceId = Context.DEVICE_ID_DEFAULT; 260 /** 261 * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not 262 * registered. 263 */ 264 @Nullable 265 private DisplayArea mDisplayArea; 266 private ActivityRecord mConfigActivityRecord; 267 // Whether the activity config override is allowed for this process. 268 private volatile boolean mIsActivityConfigOverrideAllowed = true; 269 /** Non-zero to pause dispatching process configuration change. */ 270 private int mPauseConfigurationDispatchCount; 271 272 /** 273 * Activities that hosts some UI drawn by the current process. The activities live 274 * in another process. This is used to check if the process is currently showing anything 275 * visible to the user. 276 */ 277 private static final int REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY = 1; 278 /** The activity in a different process is embedded in a task created by this process. */ 279 private static final int REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY = 1 << 1; 280 281 /** 282 * Activities that run on different processes while this process shows something in these 283 * activities or the appearance of the activities are controlled by this process. The value of 284 * map is an array of size 1 to store the kinds of remote. 285 */ 286 @Nullable 287 private ArrayMap<ActivityRecord, int[]> mRemoteActivities; 288 289 /** 290 * It can be set for a running transition player ({@link android.window.ITransitionPlayer}) or 291 * remote animators (running {@link android.window.IRemoteTransition}). 292 */ 293 static final int ANIMATING_REASON_REMOTE_ANIMATION = 1; 294 /** It is set for wakefulness transition. */ 295 static final int ANIMATING_REASON_WAKEFULNESS_CHANGE = 1 << 1; 296 297 @Retention(RetentionPolicy.SOURCE) 298 @IntDef({ 299 ANIMATING_REASON_REMOTE_ANIMATION, 300 ANIMATING_REASON_WAKEFULNESS_CHANGE, 301 }) 302 @interface AnimatingReason {} 303 304 /** 305 * Non-zero if this process is currently running an important animation. This should be never 306 * set for system server. 307 */ 308 @AnimatingReason 309 private int mAnimatingReasons; 310 311 @Retention(RetentionPolicy.SOURCE) 312 @IntDef({ 313 STOPPED_STATE_NOT_STOPPED, 314 STOPPED_STATE_FIRST_LAUNCH, 315 STOPPED_STATE_FORCE_STOPPED 316 }) 317 public @interface StoppedState {} 318 319 private volatile @StoppedState int mStoppedState; 320 321 /** 322 * Whether the stopped state was logged for an activity start, as we don't want to log 323 * multiple times. 324 */ 325 private volatile boolean mWasStoppedLogged; 326 327 // The bits used for mActivityStateFlags. 328 public static final int ACTIVITY_STATE_FLAG_IS_VISIBLE = 1 << 16; 329 public static final int ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED = 1 << 17; 330 public static final int ACTIVITY_STATE_FLAG_IS_STOPPING = 1 << 18; 331 public static final int ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING = 1 << 19; 332 public static final int ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE = 1 << 20; 333 public static final int ACTIVITY_STATE_FLAG_HAS_RESUMED = 1 << 21; 334 public static final int ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK = 1 << 22; 335 public static final int ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN = 1 << 23; 336 public static final int ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM = 1 << 24; 337 public static final int ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE = 1 << 25; 338 public static final int ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER = 0x0000ffff; 339 340 private static final int ACTIVITY_STATE_VISIBLE = 341 com.android.window.flags.Flags.useVisibleRequestedForProcessTracker() 342 ? ACTIVITY_STATE_FLAG_IS_VISIBLE 343 : ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE; 344 345 /** 346 * The state for oom-adjustment calculation. The higher 16 bits are the activity states, and the 347 * lower 16 bits are the task layer rank (see {@link Task#mLayerRank}). This field is written by 348 * window manager and read by activity manager. 349 */ 350 private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; 351 352 /** 353 * The most recent timestamp of when one of this process's stopped activities in a 354 * perceptible task became stopped. Written by window manager and read by activity manager. 355 */ 356 private volatile long mPerceptibleTaskStoppedTimeMillis = Long.MIN_VALUE; 357 WindowProcessController(@onNull ActivityTaskManagerService atm, @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner, @NonNull WindowProcessListener listener)358 public WindowProcessController(@NonNull ActivityTaskManagerService atm, 359 @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner, 360 @NonNull WindowProcessListener listener) { 361 mInfo = info; 362 mName = name; 363 mUid = uid; 364 mUserId = userId; 365 mOwner = owner; 366 mListener = listener; 367 mAtm = atm; 368 mBgLaunchController = new BackgroundLaunchProcessController( 369 atm::hasActiveVisibleWindow, atm.getBackgroundActivityStartCallback()); 370 371 boolean isSysUiPackage = info.packageName.equals( 372 mAtm.getSysUiServiceComponentLocked().getPackageName()); 373 if (isSysUiPackage || UserHandle.getAppId(mUid) == Process.SYSTEM_UID) { 374 // This is a system owned process and should not use an activity config. 375 // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs. 376 mIsActivityConfigOverrideAllowed = false; 377 } 378 mUseFifoUiScheduling = com.android.window.flags.Flags.fifoPriorityForMajorUiProcesses() 379 && (isSysUiPackage || mAtm.isCallerRecents(uid)); 380 } 381 setPid(int pid)382 public void setPid(int pid) { 383 mPid = pid; 384 } 385 getPid()386 public int getPid() { 387 return mPid; 388 } 389 390 @HotPath(caller = HotPath.PROCESS_CHANGE) setThread(IApplicationThread thread)391 public void setThread(IApplicationThread thread) { 392 synchronized (mAtm.mGlobalLockWithoutBoost) { 393 mThread = thread; 394 // In general this is called from attaching application, so the last configuration 395 // has been sent to client by {@link android.app.IApplicationThread#bindApplication}. 396 // If this process is system server, it is fine because system is booting and a new 397 // configuration will update when display is ready. 398 if (thread != null) { 399 setLastReportedConfiguration(getConfiguration()); 400 } else { 401 // The process is inactive. 402 mAtm.mVisibleActivityProcessTracker.removeProcess(this); 403 } 404 } 405 } 406 getThread()407 IApplicationThread getThread() { 408 return mThread; 409 } 410 hasThread()411 boolean hasThread() { 412 return mThread != null; 413 } 414 setCurrentSchedulingGroup(int curSchedGroup)415 public void setCurrentSchedulingGroup(int curSchedGroup) { 416 mCurSchedGroup = curSchedGroup; 417 } 418 getCurrentSchedulingGroup()419 int getCurrentSchedulingGroup() { 420 return mCurSchedGroup; 421 } 422 setCurrentProcState(int curProcState)423 public void setCurrentProcState(int curProcState) { 424 mCurProcState = curProcState; 425 } 426 getCurrentProcState()427 int getCurrentProcState() { 428 return mCurProcState; 429 } 430 setCurrentAdj(int curAdj)431 public void setCurrentAdj(int curAdj) { 432 mCurAdj = curAdj; 433 } 434 getCurrentAdj()435 int getCurrentAdj() { 436 return mCurAdj; 437 } 438 439 /** 440 * Sets the computed process state from the oom adjustment calculation. This is frequently 441 * called in activity manager's lock, so don't use window manager lock here. 442 */ 443 @HotPath(caller = HotPath.OOM_ADJUSTMENT) setReportedProcState(int repProcState)444 public void setReportedProcState(int repProcState) { 445 final int prevProcState = mRepProcState; 446 mRepProcState = repProcState; 447 448 // Deliver the cached config if the app changes from cached state to non-cached state. 449 final IApplicationThread thread = mThread; 450 if (prevProcState >= CACHED_CONFIG_PROC_STATE && repProcState < CACHED_CONFIG_PROC_STATE 451 && thread != null && mHasCachedConfiguration) { 452 final ConfigurationChangeItem configurationChangeItem; 453 synchronized (mLastReportedConfiguration) { 454 onConfigurationChangePreScheduled(mLastReportedConfiguration); 455 configurationChangeItem = new ConfigurationChangeItem( 456 mLastReportedConfiguration, mLastTopActivityDeviceId); 457 } 458 // Schedule immediately to make sure the app component (e.g. receiver, service) can get 459 // the latest configuration in their lifecycle callbacks (e.g. onReceive, onCreate). 460 try { 461 // No WM lock here. 462 mAtm.getLifecycleManager().scheduleTransactionItemNow( 463 thread, configurationChangeItem); 464 } catch (Exception e) { 465 // TODO(b/323801078): remove Exception when cleanup 466 Slog.e(TAG_CONFIGURATION, "Failed to schedule ConfigurationChangeItem=" 467 + configurationChangeItem + " owner=" + mOwner, e); 468 } 469 } 470 } 471 getReportedProcState()472 int getReportedProcState() { 473 return mRepProcState; 474 } 475 setCrashing(boolean crashing)476 public void setCrashing(boolean crashing) { 477 mCrashing = crashing; 478 } 479 handleAppCrash()480 boolean handleAppCrash() { 481 boolean hasVisibleActivity = false; 482 ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities); 483 for (int i = activities.size() - 1; i >= 0; --i) { 484 final ActivityRecord r = activities.get(i); 485 Slog.w(TAG, " Force finishing activity " 486 + r.mActivityComponent.flattenToShortString()); 487 r.detachFromProcess(); 488 if (r.isVisibleRequested()) { 489 hasVisibleActivity = true; 490 Task finishingTask = r.getTask(); 491 r.mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_CLOSE, 492 TRANSIT_FLAG_APP_CRASHED, finishingTask); 493 } 494 r.destroyIfPossible("handleAppCrashed"); 495 } 496 return hasVisibleActivity; 497 } 498 isCrashing()499 boolean isCrashing() { 500 return mCrashing; 501 } 502 setNotResponding(boolean notResponding)503 public void setNotResponding(boolean notResponding) { 504 mNotResponding = notResponding; 505 } 506 isNotResponding()507 boolean isNotResponding() { 508 return mNotResponding; 509 } 510 setPersistent(boolean persistent)511 public void setPersistent(boolean persistent) { 512 mPersistent = persistent; 513 } 514 isPersistent()515 boolean isPersistent() { 516 return mPersistent; 517 } 518 setHasForegroundServices(boolean hasForegroundServices)519 public void setHasForegroundServices(boolean hasForegroundServices) { 520 mHasForegroundServices = hasForegroundServices; 521 } 522 hasForegroundServices()523 boolean hasForegroundServices() { 524 return mHasForegroundServices; 525 } 526 hasForegroundActivities()527 boolean hasForegroundActivities() { 528 return mAtm.mTopApp == this || (mActivityStateFlags 529 & (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED 530 | ACTIVITY_STATE_FLAG_IS_STOPPING)) != 0; 531 } 532 setHasClientActivities(boolean hasClientActivities)533 public void setHasClientActivities(boolean hasClientActivities) { 534 mHasClientActivities = hasClientActivities; 535 } 536 hasClientActivities()537 boolean hasClientActivities() { 538 return mHasClientActivities; 539 } 540 setHasTopUi(boolean hasTopUi)541 public void setHasTopUi(boolean hasTopUi) { 542 mHasTopUi = hasTopUi; 543 } 544 hasTopUi()545 boolean hasTopUi() { 546 return mHasTopUi; 547 } 548 setHasOverlayUi(boolean hasOverlayUi)549 public void setHasOverlayUi(boolean hasOverlayUi) { 550 mHasOverlayUi = hasOverlayUi; 551 } 552 hasOverlayUi()553 boolean hasOverlayUi() { 554 return mHasOverlayUi; 555 } 556 setPendingUiClean(boolean hasPendingUiClean)557 public void setPendingUiClean(boolean hasPendingUiClean) { 558 mPendingUiClean = hasPendingUiClean; 559 } 560 hasPendingUiClean()561 boolean hasPendingUiClean() { 562 return mPendingUiClean; 563 } 564 565 /** @return {@code true} if the process registered to a display area as a config listener. */ registeredForDisplayAreaConfigChanges()566 boolean registeredForDisplayAreaConfigChanges() { 567 return mDisplayArea != null; 568 } 569 570 /** @return {@code true} if the process registered to an activity as a config listener. */ 571 @VisibleForTesting registeredForActivityConfigChanges()572 boolean registeredForActivityConfigChanges() { 573 return mConfigActivityRecord != null; 574 } 575 postPendingUiCleanMsg(boolean pendingUiClean)576 void postPendingUiCleanMsg(boolean pendingUiClean) { 577 // Posting on handler so WM lock isn't held when we call into AM. 578 final Message m = PooledLambda.obtainMessage( 579 WindowProcessListener::setPendingUiClean, mListener, pendingUiClean); 580 mAtm.mH.sendMessage(m); 581 } 582 setInteractionEventTime(long interactionEventTime)583 public void setInteractionEventTime(long interactionEventTime) { 584 mInteractionEventTime = interactionEventTime; 585 } 586 getInteractionEventTime()587 long getInteractionEventTime() { 588 return mInteractionEventTime; 589 } 590 setFgInteractionTime(long fgInteractionTime)591 public void setFgInteractionTime(long fgInteractionTime) { 592 mFgInteractionTime = fgInteractionTime; 593 } 594 getFgInteractionTime()595 long getFgInteractionTime() { 596 return mFgInteractionTime; 597 } 598 setWhenUnimportant(long whenUnimportant)599 public void setWhenUnimportant(long whenUnimportant) { 600 mWhenUnimportant = whenUnimportant; 601 } 602 getWhenUnimportant()603 long getWhenUnimportant() { 604 return mWhenUnimportant; 605 } 606 setRequiredAbi(String requiredAbi)607 public void setRequiredAbi(String requiredAbi) { 608 mRequiredAbi = requiredAbi; 609 } 610 getRequiredAbi()611 String getRequiredAbi() { 612 return mRequiredAbi; 613 } 614 615 /** 616 * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not 617 * registered. 618 */ 619 @VisibleForTesting 620 @Nullable getDisplayArea()621 DisplayArea getDisplayArea() { 622 return mDisplayArea; 623 } 624 setDebugging(boolean debugging)625 public void setDebugging(boolean debugging) { 626 mDebugging = debugging; 627 } 628 isDebugging()629 boolean isDebugging() { 630 return mDebugging; 631 } 632 setUsingWrapper(boolean usingWrapper)633 public void setUsingWrapper(boolean usingWrapper) { 634 mUsingWrapper = usingWrapper; 635 } 636 isUsingWrapper()637 boolean isUsingWrapper() { 638 return mUsingWrapper; 639 } 640 hasEverLaunchedActivity()641 boolean hasEverLaunchedActivity() { 642 return mLastActivityLaunchTime > 0; 643 } 644 setLastActivityLaunchTime(ActivityRecord r)645 void setLastActivityLaunchTime(ActivityRecord r) { 646 long launchTime = r.lastLaunchTime; 647 if (launchTime <= mLastActivityLaunchTime) { 648 if (launchTime < mLastActivityLaunchTime) { 649 Slog.w(TAG, 650 "Tried to set launchTime (" + launchTime + ") < mLastActivityLaunchTime (" 651 + mLastActivityLaunchTime + ")"); 652 } 653 return; 654 } 655 updateRapidActivityLaunch(r, launchTime, mLastActivityLaunchTime); 656 mLastActivityLaunchTime = launchTime; 657 } 658 updateRapidActivityLaunch(ActivityRecord r, long launchTime, long lastLaunchTime)659 void updateRapidActivityLaunch(ActivityRecord r, long launchTime, long lastLaunchTime) { 660 if (mInstrumenting || mDebugging || lastLaunchTime <= 0) { 661 return; 662 } 663 664 final WindowProcessController caller = mAtm.mProcessMap.getProcess(r.launchedFromPid); 665 if (caller != null && caller.mInstrumenting) { 666 return; 667 } 668 669 final long diff = launchTime - lastLaunchTime; 670 if (diff < RAPID_ACTIVITY_LAUNCH_MS) { 671 mRapidActivityLaunchCount++; 672 } else if (diff >= RESET_RAPID_ACTIVITY_LAUNCH_MS) { 673 mRapidActivityLaunchCount = 0; 674 } 675 676 if (mRapidActivityLaunchCount > MAX_RAPID_ACTIVITY_LAUNCH_COUNT) { 677 mRapidActivityLaunchCount = 0; 678 final Task task = r.getTask(); 679 Slog.w(TAG, "Removing task " + task.mTaskId + " because of rapid activity launch"); 680 mAtm.mH.post(() -> { 681 synchronized (mAtm.mGlobalLock) { 682 task.removeImmediately("rapid-activity-launch"); 683 } 684 mAtm.mAmInternal.killProcess(mName, mUid, "rapidActivityLaunch"); 685 }); 686 } 687 } 688 setLastActivityFinishTimeIfNeeded(long finishTime)689 void setLastActivityFinishTimeIfNeeded(long finishTime) { 690 if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) { 691 return; 692 } 693 mLastActivityFinishTime = finishTime; 694 } 695 696 /** 697 * @see BackgroundLaunchProcessController#addOrUpdateAllowBackgroundStartPrivileges(Binder, 698 * BackgroundStartPrivileges) 699 */ addOrUpdateBackgroundStartPrivileges(@onNull Binder entity, @NonNull BackgroundStartPrivileges backgroundStartPrivileges)700 public void addOrUpdateBackgroundStartPrivileges(@NonNull Binder entity, 701 @NonNull BackgroundStartPrivileges backgroundStartPrivileges) { 702 requireNonNull(entity, "entity"); 703 requireNonNull(backgroundStartPrivileges, "backgroundStartPrivileges"); 704 checkArgument(backgroundStartPrivileges.allowsAny(), 705 "backgroundStartPrivileges does not allow anything"); 706 mBgLaunchController.addOrUpdateAllowBackgroundStartPrivileges(entity, 707 backgroundStartPrivileges); 708 } 709 710 /** @see BackgroundLaunchProcessController#removeAllowBackgroundStartPrivileges(Binder) */ removeBackgroundStartPrivileges(@onNull Binder entity)711 public void removeBackgroundStartPrivileges(@NonNull Binder entity) { 712 requireNonNull(entity, "entity"); 713 mBgLaunchController.removeAllowBackgroundStartPrivileges(entity); 714 } 715 716 /** 717 * Is this WindowProcessController in the state of allowing background FGS start? 718 */ 719 @HotPath(caller = HotPath.START_SERVICE) areBackgroundFgsStartsAllowed()720 public boolean areBackgroundFgsStartsAllowed() { 721 return areBackgroundActivityStartsAllowed( 722 mAtm.getBalAppSwitchesState(), 723 BackgroundLaunchProcessController.CHECK_FOR_FGS_START).allows(); 724 } 725 areBackgroundActivityStartsAllowed( int appSwitchState, BalCheckConfiguration checkConfiguration)726 BackgroundActivityStartController.BalVerdict areBackgroundActivityStartsAllowed( 727 int appSwitchState, BalCheckConfiguration checkConfiguration) { 728 return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, 729 mInfo.packageName, appSwitchState, checkConfiguration, 730 hasActivityInVisibleTask(), mInstrumentingWithBackgroundActivityStartPrivileges, 731 mAtm.getLastStopAppSwitchesTime(), 732 mLastActivityLaunchTime, mLastActivityFinishTime); 733 } 734 735 /** 736 * Returns whether this process is allowed to close system dialogs via a background activity 737 * start token that allows the close system dialogs operation (eg. notification). 738 */ canCloseSystemDialogsByToken()739 boolean canCloseSystemDialogsByToken() { 740 return mBgLaunchController.canCloseSystemDialogsByToken(mUid); 741 } 742 743 /** 744 * Clear all bound client Uids. 745 */ clearBoundClientUids()746 public void clearBoundClientUids() { 747 mBgLaunchController.clearBalOptInBoundClientUids(); 748 } 749 750 /** 751 * Add bound client Uid. 752 */ addBoundClientUid(int clientUid, String clientPackageName, long bindFlags)753 public void addBoundClientUid(int clientUid, String clientPackageName, long bindFlags) { 754 mBgLaunchController.addBoundClientUid(clientUid, clientPackageName, bindFlags); 755 } 756 757 /** 758 * Set instrumentation-related info. 759 * 760 * If {@code instrumenting} is {@code false}, {@code sourceUid} has to be -1. 761 */ setInstrumenting(boolean instrumenting, int sourceUid, boolean hasBackgroundActivityStartPrivileges)762 public void setInstrumenting(boolean instrumenting, int sourceUid, 763 boolean hasBackgroundActivityStartPrivileges) { 764 checkArgument(instrumenting || sourceUid == -1); 765 mInstrumenting = instrumenting; 766 mInstrumentationSourceUid = sourceUid; 767 mInstrumentingWithBackgroundActivityStartPrivileges = hasBackgroundActivityStartPrivileges; 768 } 769 isInstrumenting()770 boolean isInstrumenting() { 771 return mInstrumenting; 772 } 773 774 /** Returns the uid of the active instrumentation source if there is one, otherwise -1. */ getInstrumentationSourceUid()775 int getInstrumentationSourceUid() { 776 return mInstrumentationSourceUid; 777 } 778 setPerceptible(boolean perceptible)779 public void setPerceptible(boolean perceptible) { 780 mPerceptible = perceptible; 781 } 782 isPerceptible()783 boolean isPerceptible() { 784 return mPerceptible; 785 } 786 787 @Override getChildCount()788 protected int getChildCount() { 789 return 0; 790 } 791 792 @Override getChildAt(int index)793 protected ConfigurationContainer getChildAt(int index) { 794 return null; 795 } 796 797 @Override getParent()798 protected ConfigurationContainer getParent() { 799 // Returning RootWindowContainer as the parent, so that this process controller always 800 // has full configuration and overrides (e.g. from display) are always added on top of 801 // global config. 802 return mAtm.mRootWindowContainer; 803 } 804 805 @HotPath(caller = HotPath.PROCESS_CHANGE) addPackage(String packageName)806 public void addPackage(String packageName) { 807 synchronized (mPkgList) { 808 if (!mPkgList.contains(packageName)) { 809 mPkgList.add(packageName); 810 } 811 } 812 } 813 814 @HotPath(caller = HotPath.PROCESS_CHANGE) clearPackageList()815 public void clearPackageList() { 816 synchronized (mPkgList) { 817 mPkgList.clear(); 818 } 819 } 820 containsPackage(String packageName)821 boolean containsPackage(String packageName) { 822 synchronized (mPkgList) { 823 return mPkgList.contains(packageName); 824 } 825 } 826 getPackageList()827 List<String> getPackageList() { 828 synchronized (mPkgList) { 829 return new ArrayList<>(mPkgList); 830 } 831 } 832 addActivityIfNeeded(ActivityRecord r)833 void addActivityIfNeeded(ActivityRecord r) { 834 // even if we already track this activity, note down that it has been launched 835 setLastActivityLaunchTime(r); 836 if (mActivities.contains(r)) { 837 return; 838 } 839 mActivities.add(r); 840 mHasActivities = true; 841 if (mInactiveActivities != null) { 842 mInactiveActivities.remove(r); 843 } 844 updateActivityConfigurationListener(); 845 } 846 847 /** 848 * Indicates that the given activity is no longer active in this process. 849 * 850 * @param r The running activity to be removed. 851 * @param keepAssociation {@code true} if the activity still belongs to this process but will 852 * be removed soon, e.g. destroying. From the perspective of process 853 * priority, the process is not important if it only contains activities 854 * that are being destroyed. But the association is still needed to 855 * ensure all activities are reachable from this process. 856 */ removeActivity(ActivityRecord r, boolean keepAssociation)857 void removeActivity(ActivityRecord r, boolean keepAssociation) { 858 if (keepAssociation) { 859 if (mInactiveActivities == null) { 860 mInactiveActivities = new ArrayList<>(); 861 mInactiveActivities.add(r); 862 } else if (!mInactiveActivities.contains(r)) { 863 mInactiveActivities.add(r); 864 } 865 } else if (mInactiveActivities != null) { 866 mInactiveActivities.remove(r); 867 } 868 mActivities.remove(r); 869 mHasActivities = !mActivities.isEmpty(); 870 updateActivityConfigurationListener(); 871 } 872 clearActivities()873 void clearActivities() { 874 mInactiveActivities = null; 875 mActivities.clear(); 876 mHasActivities = false; 877 updateActivityConfigurationListener(); 878 } 879 880 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasActivities()881 public boolean hasActivities() { 882 return mHasActivities; 883 } 884 885 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasVisibleActivities()886 public boolean hasVisibleActivities() { 887 return (mActivityStateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0; 888 } 889 hasActivityInVisibleTask()890 boolean hasActivityInVisibleTask() { 891 return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0; 892 } 893 894 @HotPath(caller = HotPath.LRU_UPDATE) hasActivitiesOrRecentTasks()895 public boolean hasActivitiesOrRecentTasks() { 896 return mHasActivities || mHasRecentTasks; 897 } 898 899 @Nullable getTopActivityDisplayArea()900 TaskDisplayArea getTopActivityDisplayArea() { 901 if (mActivities.isEmpty()) { 902 return null; 903 } 904 905 final int lastIndex = mActivities.size() - 1; 906 ActivityRecord topRecord = mActivities.get(lastIndex); 907 TaskDisplayArea displayArea = topRecord.getDisplayArea(); 908 909 for (int index = lastIndex - 1; index >= 0; --index) { 910 ActivityRecord nextRecord = mActivities.get(index); 911 TaskDisplayArea nextDisplayArea = nextRecord.getDisplayArea(); 912 if (nextRecord.compareTo(topRecord) > 0 && nextDisplayArea != null) { 913 topRecord = nextRecord; 914 displayArea = nextDisplayArea; 915 } 916 } 917 918 return displayArea; 919 } 920 921 /** 922 * Update the top resuming activity in process for pre-Q apps, only the top-most visible 923 * activities are allowed to be resumed per process. 924 * @return {@code true} if the activity is allowed to be resumed by compatibility 925 * restrictions, which the activity was the topmost visible activity in process or the app is 926 * targeting after Q. Note that non-focusable activity, in picture-in-picture mode for instance, 927 * does not count as a topmost activity. 928 */ updateTopResumingActivityInProcessIfNeeded(@onNull ActivityRecord activity)929 boolean updateTopResumingActivityInProcessIfNeeded(@NonNull ActivityRecord activity) { 930 if (mInfo.targetSdkVersion >= Q || mPreQTopResumedActivity == activity) { 931 return true; 932 } 933 934 if (!activity.isAttached()) { 935 // No need to update if the activity hasn't attach to any display. 936 return false; 937 } 938 939 boolean canUpdate = false; 940 final DisplayContent topDisplay = 941 (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isAttached()) 942 ? mPreQTopResumedActivity.mDisplayContent 943 : null; 944 // Update the topmost activity if current top activity is 945 // - not on any display OR 946 // - no longer visible OR 947 // - not focusable (in PiP mode for instance) 948 if (topDisplay == null 949 || !mPreQTopResumedActivity.isVisibleRequested() 950 || !mPreQTopResumedActivity.isFocusable()) { 951 canUpdate = true; 952 } 953 954 final DisplayContent display = activity.mDisplayContent; 955 // Update the topmost activity if the current top activity wasn't on top of the other one. 956 if (!canUpdate && topDisplay.compareTo(display) < 0) { 957 canUpdate = true; 958 } 959 960 // Update the topmost activity if the activity has higher z-order than the current 961 // top-resumed activity. 962 if (!canUpdate) { 963 final ActivityRecord ar = topDisplay.getActivity(r -> r == activity, 964 true /* traverseTopToBottom */, mPreQTopResumedActivity); 965 if (ar != null && ar != mPreQTopResumedActivity) { 966 canUpdate = true; 967 } 968 } 969 970 if (canUpdate) { 971 // Make sure the previous top activity in the process no longer be resumed. 972 if (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isState(RESUMED)) { 973 final TaskFragment taskFrag = mPreQTopResumedActivity.getTaskFragment(); 974 if (taskFrag != null) { 975 boolean userLeaving = taskFrag.shouldBeVisible(null); 976 taskFrag.startPausing(userLeaving, false /* uiSleeping */, 977 activity, "top-resumed-changed"); 978 } 979 } 980 mPreQTopResumedActivity = activity; 981 } 982 return canUpdate; 983 } 984 985 // TODO(365884835): remove this method with external callers. stopFreezingActivities()986 public void stopFreezingActivities() { 987 } 988 finishActivities()989 void finishActivities() { 990 ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities); 991 for (int i = 0; i < activities.size(); i++) { 992 final ActivityRecord r = activities.get(i); 993 if (!r.finishing && r.isInRootTaskLocked()) { 994 r.finishIfPossible("finish-heavy", true /* oomAdj */); 995 } 996 } 997 } 998 isInterestingToUser()999 public boolean isInterestingToUser() { 1000 synchronized (mAtm.mGlobalLock) { 1001 final int size = mActivities.size(); 1002 for (int i = 0; i < size; i++) { 1003 ActivityRecord r = mActivities.get(i); 1004 if (r.isInterestingToUserLocked()) { 1005 return true; 1006 } 1007 } 1008 if (hasEmbeddedWindow()) { 1009 return true; 1010 } 1011 } 1012 return false; 1013 } 1014 1015 /** 1016 * @return {@code true} if this process is rendering content on to a window shown by 1017 * another process. 1018 */ hasEmbeddedWindow()1019 private boolean hasEmbeddedWindow() { 1020 if (mRemoteActivities == null) return false; 1021 for (int i = mRemoteActivities.size() - 1; i >= 0; --i) { 1022 if ((mRemoteActivities.valueAt(i)[0] & REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY) == 0) { 1023 continue; 1024 } 1025 final ActivityRecord r = mRemoteActivities.keyAt(i); 1026 if (r.isInterestingToUserLocked()) { 1027 return true; 1028 } 1029 } 1030 return false; 1031 } 1032 hasRunningActivity(String packageName)1033 public boolean hasRunningActivity(String packageName) { 1034 synchronized (mAtm.mGlobalLock) { 1035 for (int i = mActivities.size() - 1; i >= 0; --i) { 1036 final ActivityRecord r = mActivities.get(i); 1037 if (packageName.equals(r.packageName)) { 1038 return true; 1039 } 1040 } 1041 } 1042 return false; 1043 } 1044 1045 // TODO(b/199277065): Re-assess how app-specific locales are applied based on UXR 1046 // TODO(b/199277729): Consider whether we need to add special casing for edge cases like 1047 // activity-embeddings etc. updateAppSpecificSettingsForAllActivitiesInPackage(String packageName, Integer nightMode, LocaleList localesOverride, @Configuration.GrammaticalGender int gender)1048 void updateAppSpecificSettingsForAllActivitiesInPackage(String packageName, Integer nightMode, 1049 LocaleList localesOverride, @Configuration.GrammaticalGender int gender) { 1050 for (int i = mActivities.size() - 1; i >= 0; --i) { 1051 final ActivityRecord r = mActivities.get(i); 1052 // Activities from other packages could be sharing this process. Only propagate updates 1053 // to those activities that are part of the package whose app-specific settings changed 1054 if (packageName.equals(r.packageName) 1055 && r.applyAppSpecificConfig(nightMode, localesOverride, gender) 1056 && r.isVisibleRequested()) { 1057 r.ensureActivityConfiguration(); 1058 } 1059 } 1060 } 1061 clearPackagePreferredForHomeActivities()1062 public void clearPackagePreferredForHomeActivities() { 1063 synchronized (mAtm.mGlobalLock) { 1064 for (int i = mActivities.size() - 1; i >= 0; --i) { 1065 final ActivityRecord r = mActivities.get(i); 1066 if (r.isActivityTypeHome()) { 1067 Log.i(TAG, "Clearing package preferred activities from " + r.packageName); 1068 try { 1069 ActivityThread.getPackageManager() 1070 .clearPackagePreferredActivities(r.packageName); 1071 } catch (RemoteException c) { 1072 // pm is in same process, this will never happen. 1073 } 1074 } 1075 } 1076 } 1077 } 1078 hasStartedActivity(ActivityRecord launchedActivity)1079 boolean hasStartedActivity(ActivityRecord launchedActivity) { 1080 for (int i = mActivities.size() - 1; i >= 0; i--) { 1081 final ActivityRecord activity = mActivities.get(i); 1082 if (launchedActivity == activity) { 1083 continue; 1084 } 1085 if (!activity.mAppStopped) { 1086 return true; 1087 } 1088 } 1089 return false; 1090 } 1091 hasResumedActivity()1092 boolean hasResumedActivity() { 1093 return (mActivityStateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0; 1094 } 1095 updateIntentForHeavyWeightActivity(Intent intent)1096 void updateIntentForHeavyWeightActivity(Intent intent) { 1097 if (mActivities.isEmpty()) { 1098 return; 1099 } 1100 ActivityRecord hist = mActivities.get(0); 1101 intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName); 1102 intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().mTaskId); 1103 } 1104 shouldKillProcessForRemovedTask(Task task)1105 boolean shouldKillProcessForRemovedTask(Task task) { 1106 for (int k = 0; k < mActivities.size(); k++) { 1107 final ActivityRecord activity = mActivities.get(k); 1108 if (!activity.mAppStopped) { 1109 // Don't kill process(es) that has an activity not stopped. 1110 return false; 1111 } 1112 final Task otherTask = activity.getTask(); 1113 if (task.mTaskId != otherTask.mTaskId && otherTask.inRecents) { 1114 // Don't kill process(es) that has an activity in a different task that is 1115 // also in recents. 1116 return false; 1117 } 1118 } 1119 return true; 1120 } 1121 releaseSomeActivities(String reason)1122 void releaseSomeActivities(String reason) { 1123 // Examine all activities currently running in the process. 1124 // Candidate activities that can be destroyed. 1125 ArrayList<ActivityRecord> candidates = null; 1126 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + this); 1127 for (int i = 0; i < mActivities.size(); i++) { 1128 final ActivityRecord r = mActivities.get(i); 1129 // First, if we find an activity that is in the process of being destroyed, 1130 // then we just aren't going to do anything for now; we want things to settle 1131 // down before we try to prune more activities. 1132 if (r.finishing || r.isState(DESTROYING, DESTROYED)) { 1133 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r); 1134 return; 1135 } 1136 // Don't consider any activities that are currently not in a state where they 1137 // can be destroyed. 1138 if (r.isVisibleRequested() || !r.mAppStopped || !r.hasSavedState() || !r.isDestroyable() 1139 || r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING)) { 1140 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r); 1141 continue; 1142 } 1143 1144 if (r.getParent() != null) { 1145 if (candidates == null) { 1146 candidates = new ArrayList<>(); 1147 } 1148 candidates.add(r); 1149 } 1150 } 1151 1152 if (candidates != null) { 1153 // Sort based on z-order in hierarchy. 1154 candidates.sort(WindowContainer::compareTo); 1155 // Release some older activities 1156 int maxRelease = Math.max(candidates.size(), 1); 1157 do { 1158 final ActivityRecord r = candidates.remove(0); 1159 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + r 1160 + " in state " + r.getState() + " for reason " + reason); 1161 r.destroyImmediately(reason); 1162 --maxRelease; 1163 } while (maxRelease > 0); 1164 } 1165 } 1166 1167 /** 1168 * Returns display UI context list which there is any app window shows or starting activities 1169 * in this process. 1170 */ getDisplayContextsWithErrorDialogs(List<Context> displayContexts)1171 public void getDisplayContextsWithErrorDialogs(List<Context> displayContexts) { 1172 if (displayContexts == null) { 1173 return; 1174 } 1175 synchronized (mAtm.mGlobalLock) { 1176 final RootWindowContainer root = mAtm.mWindowManager.mRoot; 1177 root.getDisplayContextsWithNonToastVisibleWindows(mPid, displayContexts); 1178 1179 for (int i = mActivities.size() - 1; i >= 0; --i) { 1180 final ActivityRecord r = mActivities.get(i); 1181 final int displayId = r.getDisplayId(); 1182 final Context c = root.getDisplayUiContext(displayId); 1183 1184 if (c != null && r.isVisibleRequested() && !displayContexts.contains(c)) { 1185 displayContexts.add(c); 1186 } 1187 } 1188 } 1189 } 1190 1191 /** Adds an activity that hosts UI drawn by the current process. */ addHostActivity(ActivityRecord r)1192 void addHostActivity(ActivityRecord r) { 1193 final int[] flags = getRemoteActivityFlags(r); 1194 flags[0] |= REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY; 1195 } 1196 1197 /** Removes an activity that hosts UI drawn by the current process. */ removeHostActivity(ActivityRecord r)1198 void removeHostActivity(ActivityRecord r) { 1199 removeRemoteActivityFlags(r, REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY); 1200 } 1201 1202 /** Adds an embedded activity in a different process to this process that organizes it. */ addEmbeddedActivity(ActivityRecord r)1203 void addEmbeddedActivity(ActivityRecord r) { 1204 final int[] flags = getRemoteActivityFlags(r); 1205 flags[0] |= REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY; 1206 } 1207 1208 /** Removes an embedded activity which was added by {@link #addEmbeddedActivity}. */ removeEmbeddedActivity(ActivityRecord r)1209 void removeEmbeddedActivity(ActivityRecord r) { 1210 removeRemoteActivityFlags(r, REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY); 1211 } 1212 getRemoteActivityFlags(ActivityRecord r)1213 private int[] getRemoteActivityFlags(ActivityRecord r) { 1214 if (mRemoteActivities == null) { 1215 mRemoteActivities = new ArrayMap<>(); 1216 } 1217 int[] flags = mRemoteActivities.get(r); 1218 if (flags == null) { 1219 mRemoteActivities.put(r, flags = new int[1]); 1220 } 1221 return flags; 1222 } 1223 removeRemoteActivityFlags(ActivityRecord r, int flags)1224 private void removeRemoteActivityFlags(ActivityRecord r, int flags) { 1225 if (mRemoteActivities == null) return; 1226 final int index = mRemoteActivities.indexOfKey(r); 1227 if (index < 0) return; 1228 final int[] currentFlags = mRemoteActivities.valueAt(index); 1229 currentFlags[0] &= ~flags; 1230 if (currentFlags[0] == 0) { 1231 mRemoteActivities.removeAt(index); 1232 } 1233 } 1234 1235 /** 1236 * Returns the current ACTIVITY_STATE_FLAG_* of this process. It should only be called if 1237 * {@link #hasActivities} returns {@code true}. 1238 */ 1239 @HotPath(caller = HotPath.OOM_ADJUSTMENT) getActivityStateFlags()1240 public int getActivityStateFlags() { 1241 return mActivityStateFlags; 1242 } 1243 1244 /** 1245 * Returns the most recent timestamp when one of this process's stopped activities in a 1246 * perceptible task became stopped. It should only be called if {@link #hasActivities} 1247 * returns {@code true} and {@link #getActivityStateFlags} does not have any of 1248 * the ACTIVITY_STATE_FLAG_IS_(VISIBLE|PAUSING_OR_PAUSED|STOPPING) bit set. 1249 */ 1250 @HotPath(caller = HotPath.OOM_ADJUSTMENT) getPerceptibleTaskStoppedTimeMillis()1251 public long getPerceptibleTaskStoppedTimeMillis() { 1252 return mPerceptibleTaskStoppedTimeMillis; 1253 } 1254 computeProcessActivityState()1255 void computeProcessActivityState() { 1256 // Since there could be more than one activities in a process record, we don't need to 1257 // compute the OomAdj with each of them, just need to find out the activity with the 1258 // "best" state, the order would be visible, pausing, stopping... 1259 ActivityRecord.State bestInvisibleState = DESTROYED; 1260 boolean allStoppingFinishing = true; 1261 boolean visible = false; 1262 boolean hasResumedFreeform = false; 1263 int minTaskLayer = Integer.MAX_VALUE; 1264 int stateFlags = 0; 1265 int nonOccludedRatio = 0; 1266 long perceptibleTaskStoppedTimeMillis = Long.MIN_VALUE; 1267 final boolean wasResumed = hasResumedActivity(); 1268 final boolean wasAnyVisible = (mActivityStateFlags & ACTIVITY_STATE_VISIBLE) != 0; 1269 for (int i = mActivities.size() - 1; i >= 0; i--) { 1270 final ActivityRecord r = mActivities.get(i); 1271 if (r.isVisible()) { 1272 stateFlags |= ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE; 1273 } 1274 final Task task = r.getTask(); 1275 if (task == null) { 1276 Slog.e(TAG, "Unexpected detached " + r + " in " + this); 1277 continue; 1278 } 1279 if (task.mLayerRank != Task.LAYER_RANK_INVISIBLE) { 1280 stateFlags |= ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK; 1281 } 1282 final ActivityRecord.State state = r.getState(); 1283 if (r.isVisibleRequested()) { 1284 if (state == RESUMED) { 1285 stateFlags |= ACTIVITY_STATE_FLAG_HAS_RESUMED; 1286 final int windowingMode = r.getWindowingMode(); 1287 if (windowingMode == WINDOWING_MODE_MULTI_WINDOW 1288 && com.android.window.flags.Flags 1289 .processPriorityPolicyForMultiWindowMode() 1290 && task.hasAdjacentTask()) { 1291 stateFlags |= ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN; 1292 } else if (windowingMode == WINDOWING_MODE_FREEFORM) { 1293 hasResumedFreeform = true; 1294 nonOccludedRatio = 1295 Math.max(task.mNonOccludedFreeformAreaRatio, nonOccludedRatio); 1296 } 1297 } 1298 if (minTaskLayer > 0) { 1299 final int layer = task.mLayerRank; 1300 if (layer >= 0 && minTaskLayer > layer) { 1301 minTaskLayer = layer; 1302 } 1303 } 1304 visible = true; 1305 // continue the loop, in case there are multiple visible activities in 1306 // this process, we'd find out the one with the minimal layer, thus it'll 1307 // get a higher adj score. 1308 } else if (!visible && bestInvisibleState != PAUSING) { 1309 if (state == PAUSING) { 1310 bestInvisibleState = PAUSING; 1311 // Treat PAUSING as visible in case the next activity in the same process has 1312 // not yet been set as visible-requested. 1313 if (com.android.window.flags.Flags.useVisibleRequestedForProcessTracker() 1314 && r.isVisible()) { 1315 stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE; 1316 } 1317 } else if (state == PAUSED) { 1318 bestInvisibleState = PAUSED; 1319 } else if (state == STOPPING) { 1320 bestInvisibleState = STOPPING; 1321 // Not "finishing" if any of activity isn't finishing. 1322 allStoppingFinishing &= r.finishing; 1323 } else if (bestInvisibleState == DESTROYED && state == STOPPED) { 1324 if (task.mIsPerceptible) { 1325 perceptibleTaskStoppedTimeMillis = 1326 Long.max(r.mStoppedTime, perceptibleTaskStoppedTimeMillis); 1327 } 1328 } 1329 } 1330 } 1331 if (mRemoteActivities != null) { 1332 // Make this process have visible state if its organizer embeds visible activities of 1333 // other process, so this process can be responsive for the organizer events. 1334 for (int i = mRemoteActivities.size() - 1; i >= 0; i--) { 1335 if ((mRemoteActivities.valueAt(i)[0] & REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY) != 0 1336 && mRemoteActivities.keyAt(i).isVisibleRequested()) { 1337 stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE; 1338 } 1339 } 1340 } 1341 1342 if (hasResumedFreeform 1343 && com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode() 1344 // Exclude task layer 1 because it is already the top most. 1345 && minTaskLayer > 1) { 1346 if (minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM 1347 || nonOccludedRatio >= PERCEPTIBLE_FREEFORM_VISIBLE_RATIO) { 1348 stateFlags |= ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM; 1349 } else { 1350 stateFlags |= ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE; 1351 } 1352 } 1353 stateFlags |= minTaskLayer & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; 1354 if (visible) { 1355 stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE; 1356 } else if (bestInvisibleState == PAUSING || bestInvisibleState == PAUSED) { 1357 stateFlags |= ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED; 1358 } else if (bestInvisibleState == STOPPING) { 1359 stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING; 1360 if (allStoppingFinishing) { 1361 stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING; 1362 } 1363 } 1364 mActivityStateFlags = stateFlags; 1365 mPerceptibleTaskStoppedTimeMillis = perceptibleTaskStoppedTimeMillis; 1366 1367 final boolean anyVisible = (stateFlags & ACTIVITY_STATE_VISIBLE) != 0; 1368 if (!wasAnyVisible && anyVisible) { 1369 mAtm.mVisibleActivityProcessTracker.onAnyActivityVisible(this); 1370 mAtm.mWindowManager.onProcessActivityVisibilityChanged(mUid, true /*visible*/); 1371 } else if (wasAnyVisible && !anyVisible) { 1372 mAtm.mVisibleActivityProcessTracker.onAllActivitiesInvisible(this); 1373 mAtm.mWindowManager.onProcessActivityVisibilityChanged(mUid, false /*visible*/); 1374 } else if (wasAnyVisible && !wasResumed && hasResumedActivity()) { 1375 mAtm.mVisibleActivityProcessTracker.onActivityResumedWhileVisible(this); 1376 } 1377 } 1378 1379 /** Called when the process has some oom related changes and it is going to update oom-adj. */ prepareOomAdjustment()1380 private void prepareOomAdjustment() { 1381 mAtm.mRootWindowContainer.rankTaskLayers(); 1382 mAtm.mTaskSupervisor.computeProcessActivityStateBatch(); 1383 } 1384 computeRelaunchReason()1385 public int computeRelaunchReason() { 1386 synchronized (mAtm.mGlobalLock) { 1387 final int activitiesSize = mActivities.size(); 1388 for (int i = activitiesSize - 1; i >= 0; i--) { 1389 final ActivityRecord r = mActivities.get(i); 1390 if (r.mRelaunchReason != RELAUNCH_REASON_NONE) { 1391 return r.mRelaunchReason; 1392 } 1393 } 1394 } 1395 return RELAUNCH_REASON_NONE; 1396 } 1397 1398 /** 1399 * Get the current dispatching timeout. If instrumentation is currently taking place, return 1400 * a longer value. Shorter timeout is returned otherwise. 1401 * @return The timeout in milliseconds 1402 */ getInputDispatchingTimeoutMillis()1403 public long getInputDispatchingTimeoutMillis() { 1404 synchronized (mAtm.mGlobalLock) { 1405 return isInstrumenting() || isUsingWrapper() 1406 ? INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS : 1407 DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 1408 } 1409 } 1410 clearProfilerIfNeeded()1411 void clearProfilerIfNeeded() { 1412 // Posting on handler so WM lock isn't held when we call into AM. 1413 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1414 WindowProcessListener::clearProfilerIfNeeded, mListener)); 1415 } 1416 updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, boolean updateOomAdj, boolean addPendingTopUid)1417 void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, 1418 boolean updateOomAdj, boolean addPendingTopUid) { 1419 if (addPendingTopUid) { 1420 addToPendingTop(); 1421 } 1422 if (updateOomAdj) { 1423 prepareOomAdjustment(); 1424 } 1425 // Posting on handler so WM lock isn't held when we call into AM. 1426 final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo, 1427 mListener, updateServiceConnectionActivities, activityChange, updateOomAdj); 1428 mAtm.mH.sendMessage(m); 1429 } 1430 1431 /** Refreshes oom adjustment and process state of this process. */ scheduleUpdateOomAdj()1432 void scheduleUpdateOomAdj() { 1433 mAtm.mH.sendMessage(PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo, 1434 mListener, false /* updateServiceConnectionActivities */, 1435 false /* activityChange */, true /* updateOomAdj */)); 1436 } 1437 1438 /** Makes the process have top state before oom-adj is computed from a posted message. */ addToPendingTop()1439 void addToPendingTop() { 1440 mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread); 1441 } 1442 updateServiceConnectionActivities()1443 void updateServiceConnectionActivities() { 1444 // Posting on handler so WM lock isn't held when we call into AM. 1445 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1446 WindowProcessListener::updateServiceConnectionActivities, mListener)); 1447 } 1448 setPendingUiCleanAndForceProcessStateUpTo(int newState)1449 void setPendingUiCleanAndForceProcessStateUpTo(int newState) { 1450 // Posting on handler so WM lock isn't held when we call into AM. 1451 final Message m = PooledLambda.obtainMessage( 1452 WindowProcessListener::setPendingUiCleanAndForceProcessStateUpTo, 1453 mListener, newState); 1454 mAtm.mH.sendMessage(m); 1455 } 1456 isRemoved()1457 boolean isRemoved() { 1458 return mListener.isRemoved(); 1459 } 1460 shouldSetProfileProc()1461 private boolean shouldSetProfileProc() { 1462 return mAtm.mProfileApp != null && mAtm.mProfileApp.equals(mName) 1463 && (mAtm.mProfileProc == null || mAtm.mProfileProc == this); 1464 } 1465 createProfilerInfoIfNeeded()1466 ProfilerInfo createProfilerInfoIfNeeded() { 1467 final ProfilerInfo currentProfilerInfo = mAtm.mProfilerInfo; 1468 if (currentProfilerInfo == null || currentProfilerInfo.profileFile == null 1469 || !shouldSetProfileProc()) { 1470 return null; 1471 } 1472 if (currentProfilerInfo.profileFd != null) { 1473 try { 1474 currentProfilerInfo.profileFd = currentProfilerInfo.profileFd.dup(); 1475 } catch (IOException e) { 1476 currentProfilerInfo.closeFd(); 1477 } 1478 } 1479 return new ProfilerInfo(currentProfilerInfo); 1480 } 1481 onStartActivity(int topProcessState, ActivityInfo info)1482 void onStartActivity(int topProcessState, ActivityInfo info) { 1483 String packageName = null; 1484 if ((info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0 1485 || !"android".equals(info.packageName)) { 1486 // Don't add this if it is a platform component that is marked to run in multiple 1487 // processes, because this is actually part of the framework so doesn't make sense 1488 // to track as a separate apk in the process. 1489 packageName = info.packageName; 1490 } 1491 // update ActivityManagerService.PendingStartActivityUids list. 1492 if (topProcessState == ActivityManager.PROCESS_STATE_TOP) { 1493 mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread); 1494 } 1495 prepareOomAdjustment(); 1496 // Posting the message at the front of queue so WM lock isn't held when we call into AM, 1497 // and the process state of starting activity can be updated quicker which will give it a 1498 // higher scheduling group. 1499 final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity, 1500 mListener, topProcessState, shouldSetProfileProc(), packageName, 1501 info.applicationInfo.longVersionCode); 1502 mAtm.mH.sendMessageAtFrontOfQueue(m); 1503 } 1504 appDied(String reason)1505 void appDied(String reason) { 1506 // Posting on handler so WM lock isn't held when we call into AM. 1507 final Message m = PooledLambda.obtainMessage( 1508 WindowProcessListener::appDied, mListener, reason); 1509 mAtm.mH.sendMessage(m); 1510 } 1511 1512 /** 1513 * Clean up the activities belonging to this process. 1514 * 1515 * @return {@code true} if the process has any visible activity. 1516 */ handleAppDied()1517 boolean handleAppDied() { 1518 mAtm.mTaskSupervisor.removeHistoryRecords(this); 1519 1520 boolean hasVisibleActivities = false; 1521 final boolean hasInactiveActivities = 1522 mInactiveActivities != null && !mInactiveActivities.isEmpty(); 1523 final ArrayList<ActivityRecord> activities = 1524 (mHasActivities || hasInactiveActivities) ? new ArrayList<>() : mActivities; 1525 if (mHasActivities) { 1526 activities.addAll(mActivities); 1527 } 1528 if (hasInactiveActivities) { 1529 // Make sure that all activities in this process are handled. 1530 activities.addAll(mInactiveActivities); 1531 } 1532 if (isRemoved()) { 1533 // The package of the died process should be force-stopped, so make its activities as 1534 // finishing to prevent the process from being started again if the next top (or being 1535 // visible) activity also resides in the same process. This must be done before removal. 1536 for (int i = activities.size() - 1; i >= 0; i--) { 1537 activities.get(i).makeFinishingLocked(); 1538 } 1539 } 1540 for (int i = activities.size() - 1; i >= 0; i--) { 1541 final ActivityRecord r = activities.get(i); 1542 if (r.isVisibleRequested() || r.isVisible()) { 1543 // While an activity launches a new activity, it's possible that the old activity 1544 // is already requested to be hidden (mVisibleRequested=false), but this visibility 1545 // is not yet committed, so isVisible()=true. 1546 hasVisibleActivities = true; 1547 } 1548 1549 final TaskFragment taskFragment = r.getTaskFragment(); 1550 if (taskFragment != null) { 1551 // There may be a pausing activity that hasn't shown any window and was requested 1552 // to be hidden. But pausing is also a visible state, it should be regarded as 1553 // visible, so the caller can know the next activity should be resumed. 1554 hasVisibleActivities |= taskFragment.handleAppDied(this); 1555 } 1556 r.handleAppDied(); 1557 } 1558 clearRecentTasks(); 1559 clearActivities(); 1560 1561 return hasVisibleActivities; 1562 } 1563 registerDisplayAreaConfigurationListener(@ullable DisplayArea displayArea)1564 void registerDisplayAreaConfigurationListener(@Nullable DisplayArea displayArea) { 1565 if (displayArea == null || displayArea.containsListener(this)) { 1566 return; 1567 } 1568 unregisterConfigurationListeners(); 1569 mDisplayArea = displayArea; 1570 displayArea.registerConfigurationChangeListener(this); 1571 } 1572 1573 @VisibleForTesting unregisterDisplayAreaConfigurationListener()1574 void unregisterDisplayAreaConfigurationListener() { 1575 if (mDisplayArea == null) { 1576 return; 1577 } 1578 mDisplayArea.unregisterConfigurationChangeListener(this); 1579 mDisplayArea = null; 1580 onMergedOverrideConfigurationChanged(Configuration.EMPTY); 1581 } 1582 registerActivityConfigurationListener(ActivityRecord activityRecord)1583 void registerActivityConfigurationListener(ActivityRecord activityRecord) { 1584 if (activityRecord == null || activityRecord.containsListener(this) 1585 // Check for the caller from outside of this class. 1586 || !mIsActivityConfigOverrideAllowed) { 1587 return; 1588 } 1589 unregisterConfigurationListeners(); 1590 mConfigActivityRecord = activityRecord; 1591 activityRecord.registerConfigurationChangeListener(this); 1592 // If the process hasn't attached, make sure that prepareConfigurationForLaunchingActivity 1593 // will use the newer configuration sequence. 1594 if (mThread == null) { 1595 mHasPendingConfigurationChange = true; 1596 } 1597 } 1598 unregisterActivityConfigurationListener()1599 private void unregisterActivityConfigurationListener() { 1600 if (mConfigActivityRecord == null) { 1601 return; 1602 } 1603 mConfigActivityRecord.unregisterConfigurationChangeListener(this); 1604 mConfigActivityRecord = null; 1605 onMergedOverrideConfigurationChanged(Configuration.EMPTY); 1606 } 1607 1608 /** 1609 * A process can only register to one {@link WindowContainer} to listen to the override 1610 * configuration changes. Unregisters the existing listener if it has one before registers a 1611 * new one. 1612 */ unregisterConfigurationListeners()1613 private void unregisterConfigurationListeners() { 1614 unregisterActivityConfigurationListener(); 1615 unregisterDisplayAreaConfigurationListener(); 1616 } 1617 1618 /** 1619 * Destroys the WindwoProcessController, after the process has been removed. 1620 */ destroy()1621 void destroy() { 1622 unregisterConfigurationListeners(); 1623 } 1624 1625 /** 1626 * Check if activity configuration override for the activity process needs an update and perform 1627 * if needed. By default we try to override the process configuration to match the top activity 1628 * config to increase app compatibility with multi-window and multi-display. The process will 1629 * always track the configuration of the non-finishing activity last added to the process. 1630 */ updateActivityConfigurationListener()1631 private void updateActivityConfigurationListener() { 1632 if (!mIsActivityConfigOverrideAllowed) { 1633 return; 1634 } 1635 1636 for (int i = mActivities.size() - 1; i >= 0; i--) { 1637 final ActivityRecord activityRecord = mActivities.get(i); 1638 if (!activityRecord.finishing) { 1639 // Eligible activity is found, update listener. 1640 registerActivityConfigurationListener(activityRecord); 1641 return; 1642 } 1643 } 1644 1645 // No eligible activities found, let's remove the configuration listener. 1646 unregisterActivityConfigurationListener(); 1647 } 1648 1649 @Override onConfigurationChanged(Configuration newGlobalConfig)1650 public void onConfigurationChanged(Configuration newGlobalConfig) { 1651 super.onConfigurationChanged(newGlobalConfig); 1652 1653 // If deviceId for the top-activity changed, schedule passing it to the app process. 1654 boolean topActivityDeviceChanged = false; 1655 int deviceId = getTopActivityDeviceId(); 1656 if (deviceId != mLastTopActivityDeviceId) { 1657 topActivityDeviceChanged = true; 1658 mLastTopActivityDeviceId = deviceId; 1659 } 1660 1661 final Configuration config = getConfiguration(); 1662 if (mLastReportedConfiguration.equals(config) & !topActivityDeviceChanged) { 1663 // Nothing changed. 1664 if (Build.IS_DEBUGGABLE && mHasImeService) { 1665 // TODO (b/135719017): Temporary log for debugging IME service. 1666 Slog.w(TAG_CONFIGURATION, "Current config: " + config 1667 + " unchanged for IME proc " + mName); 1668 } 1669 return; 1670 } 1671 1672 if (mPauseConfigurationDispatchCount > 0) { 1673 mHasPendingConfigurationChange = true; 1674 return; 1675 } 1676 1677 dispatchConfiguration(config); 1678 } 1679 getTopActivityDeviceId()1680 private int getTopActivityDeviceId() { 1681 ActivityRecord topActivity = getTopNonFinishingActivity(); 1682 int updatedDeviceId = Context.DEVICE_ID_DEFAULT; 1683 if (topActivity != null && topActivity.mDisplayContent != null) { 1684 updatedDeviceId = mAtm.mTaskSupervisor.getDeviceIdForDisplayId( 1685 topActivity.mDisplayContent.mDisplayId); 1686 } 1687 return updatedDeviceId; 1688 } 1689 1690 @Nullable getTopNonFinishingActivity()1691 private ActivityRecord getTopNonFinishingActivity() { 1692 if (mActivities.isEmpty()) { 1693 return null; 1694 } 1695 for (int i = mActivities.size() - 1; i >= 0; i--) { 1696 if (!mActivities.get(i).finishing) { 1697 return mActivities.get(i); 1698 } 1699 } 1700 return null; 1701 } 1702 1703 @Override onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig)1704 public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) { 1705 super.onRequestedOverrideConfigurationChanged(mergedOverrideConfig); 1706 } 1707 1708 @Override resolveOverrideConfiguration(Configuration newParentConfig)1709 void resolveOverrideConfiguration(Configuration newParentConfig) { 1710 final Configuration requestedOverrideConfig = getRequestedOverrideConfiguration(); 1711 if (requestedOverrideConfig.assetsSeq != ASSETS_SEQ_UNDEFINED 1712 && newParentConfig.assetsSeq > requestedOverrideConfig.assetsSeq) { 1713 requestedOverrideConfig.assetsSeq = ASSETS_SEQ_UNDEFINED; 1714 } 1715 super.resolveOverrideConfiguration(newParentConfig); 1716 final Configuration resolvedConfig = getResolvedOverrideConfiguration(); 1717 // Make sure that we don't accidentally override the activity type. 1718 resolvedConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); 1719 // Activity has an independent ActivityRecord#mConfigurationSeq. If this process registers 1720 // activity configuration, its config seq shouldn't go backwards by activity configuration. 1721 // Otherwise if other places send wpc.getConfiguration() to client, the configuration may 1722 // be ignored due to the seq is older. 1723 resolvedConfig.seq = newParentConfig.seq; 1724 1725 if (mConfigActivityRecord != null) { 1726 // Let the activity decide whether to apply the size override. 1727 return; 1728 } 1729 final DisplayContent displayContent = mAtm.mWindowManager != null 1730 ? mAtm.mWindowManager.getDefaultDisplayContentLocked() 1731 : null; 1732 applySizeOverrideIfNeeded( 1733 displayContent, 1734 mInfo, 1735 newParentConfig, 1736 resolvedConfig, 1737 false /* optsOutEdgeToEdge */, 1738 false /* hasFixedRotationTransform */, 1739 false /* hasCompatDisplayInsets */, 1740 null /* task */); 1741 } 1742 dispatchConfiguration(@onNull Configuration config)1743 void dispatchConfiguration(@NonNull Configuration config) { 1744 mHasPendingConfigurationChange = false; 1745 final IApplicationThread thread = mThread; 1746 if (thread == null) { 1747 if (Build.IS_DEBUGGABLE && mHasImeService) { 1748 // TODO (b/135719017): Temporary log for debugging IME service. 1749 Slog.w(TAG_CONFIGURATION, "Unable to send config for IME proc " + mName 1750 + ": no app thread"); 1751 } 1752 return; 1753 } 1754 1755 config.seq = mAtm.increaseConfigurationSeqLocked(); 1756 setLastReportedConfiguration(config); 1757 1758 // A cached process doesn't have running application components, so it is unnecessary to 1759 // notify the configuration change. The last-reported-configuration is still set because 1760 // setReportedProcState() should not write any fields that require WM lock. 1761 if (mRepProcState >= CACHED_CONFIG_PROC_STATE) { 1762 mHasCachedConfiguration = true; 1763 // Because there are 2 volatile accesses in setReportedProcState(): mRepProcState and 1764 // mHasCachedConfiguration, check again in case mRepProcState is changed but hasn't 1765 // read the change of mHasCachedConfiguration. 1766 if (mRepProcState >= CACHED_CONFIG_PROC_STATE) { 1767 return; 1768 } 1769 } 1770 1771 onConfigurationChangePreScheduled(config); 1772 scheduleClientTransactionItem( 1773 thread, new ConfigurationChangeItem(config, mLastTopActivityDeviceId)); 1774 } 1775 onConfigurationChangePreScheduled(@onNull Configuration config)1776 private void onConfigurationChangePreScheduled(@NonNull Configuration config) { 1777 ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName, 1778 config); 1779 if (Build.IS_DEBUGGABLE && mHasImeService) { 1780 // TODO (b/135719017): Temporary log for debugging IME service. 1781 Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config); 1782 } 1783 mHasCachedConfiguration = false; 1784 } 1785 1786 @VisibleForTesting scheduleClientTransactionItem(@onNull ClientTransactionItem transactionItem)1787 void scheduleClientTransactionItem(@NonNull ClientTransactionItem transactionItem) { 1788 final IApplicationThread thread = mThread; 1789 if (thread == null) { 1790 if (Build.IS_DEBUGGABLE) { 1791 Slog.w(TAG_CONFIGURATION, "Unable to send transaction to client proc " + mName 1792 + ": no app thread"); 1793 } 1794 return; 1795 } 1796 scheduleClientTransactionItem(thread, transactionItem); 1797 } 1798 scheduleClientTransactionItem(@onNull IApplicationThread thread, @NonNull ClientTransactionItem transactionItem)1799 private void scheduleClientTransactionItem(@NonNull IApplicationThread thread, 1800 @NonNull ClientTransactionItem transactionItem) { 1801 try { 1802 if (mWindowSession != null && mWindowSession.hasWindow()) { 1803 mAtm.getLifecycleManager().scheduleTransactionItem(thread, transactionItem); 1804 } else { 1805 // Non-UI process can handle the change directly. 1806 mAtm.getLifecycleManager().scheduleTransactionItemNow(thread, transactionItem); 1807 } 1808 } catch (RemoteException e) { 1809 // TODO(b/323801078): remove Exception when cleanup 1810 // Expected if the process has been killed. 1811 Slog.w(TAG_CONFIGURATION, "Failed for dead process. ClientTransactionItem=" 1812 + transactionItem + " owner=" + mOwner); 1813 } 1814 } 1815 setLastReportedConfiguration(Configuration config)1816 void setLastReportedConfiguration(Configuration config) { 1817 // Synchronize for the access from setReportedProcState(). 1818 synchronized (mLastReportedConfiguration) { 1819 mLastReportedConfiguration.setTo(config); 1820 } 1821 } 1822 pauseConfigurationDispatch()1823 void pauseConfigurationDispatch() { 1824 mPauseConfigurationDispatchCount++; 1825 } 1826 1827 /** Returns {@code true} if the configuration change is pending to dispatch. */ resumeConfigurationDispatch()1828 boolean resumeConfigurationDispatch() { 1829 if (mPauseConfigurationDispatchCount == 0) { 1830 return false; 1831 } 1832 mPauseConfigurationDispatchCount--; 1833 return mHasPendingConfigurationChange; 1834 } 1835 updateAssetConfiguration(int assetSeq)1836 void updateAssetConfiguration(int assetSeq) { 1837 // Update the process override configuration directly if the process configuration will 1838 // not be override from its activities. 1839 if (!mHasActivities || !mIsActivityConfigOverrideAllowed) { 1840 Configuration overrideConfig = new Configuration(getRequestedOverrideConfiguration()); 1841 overrideConfig.assetsSeq = assetSeq; 1842 onRequestedOverrideConfigurationChanged(overrideConfig); 1843 return; 1844 } 1845 1846 // Otherwise, we can just update the activity override configuration. 1847 for (int i = mActivities.size() - 1; i >= 0; i--) { 1848 ActivityRecord r = mActivities.get(i); 1849 Configuration overrideConfig = new Configuration(r.getRequestedOverrideConfiguration()); 1850 overrideConfig.assetsSeq = assetSeq; 1851 r.onRequestedOverrideConfigurationChanged(overrideConfig); 1852 r.updateApplicationInfo(mInfo); 1853 if (r.isVisibleRequested()) { 1854 r.ensureActivityConfiguration(); 1855 } 1856 } 1857 } 1858 updateApplicationInfo(ApplicationInfo aInfo)1859 public void updateApplicationInfo(ApplicationInfo aInfo) { 1860 mInfo = aInfo; 1861 } 1862 1863 /** 1864 * This is called for sending {@link android.app.servertransaction.LaunchActivityItem}. 1865 * The caller must call {@link #setLastReportedConfiguration} if the delivered configuration 1866 * is newer. 1867 */ prepareConfigurationForLaunchingActivity()1868 Configuration prepareConfigurationForLaunchingActivity() { 1869 final Configuration config = getConfiguration(); 1870 if (mHasPendingConfigurationChange) { 1871 mHasPendingConfigurationChange = false; 1872 // The global configuration may not change, so the client process may have the same 1873 // config seq. This increment ensures that the client won't ignore the configuration. 1874 config.seq = mAtm.increaseConfigurationSeqLocked(); 1875 } 1876 // LaunchActivityItem includes the latest process configuration. 1877 mHasCachedConfiguration = false; 1878 return config; 1879 } 1880 1881 /** Returns the total time (in milliseconds) spent executing in both user and system code. */ getCpuTime()1882 public long getCpuTime() { 1883 return mListener.getCpuTime(); 1884 } 1885 addRecentTask(Task task)1886 void addRecentTask(Task task) { 1887 mRecentTasks.add(task); 1888 mHasRecentTasks = true; 1889 } 1890 removeRecentTask(Task task)1891 void removeRecentTask(Task task) { 1892 mRecentTasks.remove(task); 1893 mHasRecentTasks = !mRecentTasks.isEmpty(); 1894 } 1895 1896 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasRecentTasks()1897 public boolean hasRecentTasks() { 1898 return mHasRecentTasks; 1899 } 1900 clearRecentTasks()1901 void clearRecentTasks() { 1902 for (int i = mRecentTasks.size() - 1; i >= 0; i--) { 1903 mRecentTasks.get(i).clearRootProcess(); 1904 } 1905 mRecentTasks.clear(); 1906 mHasRecentTasks = false; 1907 } 1908 appEarlyNotResponding(String annotation, Runnable killAppCallback)1909 public void appEarlyNotResponding(String annotation, Runnable killAppCallback) { 1910 Runnable targetRunnable = null; 1911 synchronized (mAtm.mGlobalLock) { 1912 if (mAtm.mController == null) { 1913 return; 1914 } 1915 1916 try { 1917 // 0 == continue, -1 = kill process immediately 1918 int res = mAtm.mController.appEarlyNotResponding(mName, mPid, annotation); 1919 if (res < 0 && mPid != MY_PID) { 1920 targetRunnable = killAppCallback; 1921 } 1922 } catch (RemoteException e) { 1923 mAtm.mController = null; 1924 Watchdog.getInstance().setActivityController(null); 1925 } 1926 } 1927 if (targetRunnable != null) { 1928 targetRunnable.run(); 1929 } 1930 } 1931 appNotResponding(String info, Runnable killAppCallback, Runnable serviceTimeoutCallback)1932 public boolean appNotResponding(String info, Runnable killAppCallback, 1933 Runnable serviceTimeoutCallback) { 1934 Runnable targetRunnable = null; 1935 synchronized (mAtm.mGlobalLock) { 1936 if (mAtm.mController == null) { 1937 return false; 1938 } 1939 1940 try { 1941 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately 1942 int res = mAtm.mController.appNotResponding(mName, mPid, info); 1943 if (res != 0) { 1944 if (res < 0 && mPid != MY_PID) { 1945 targetRunnable = killAppCallback; 1946 } else { 1947 targetRunnable = serviceTimeoutCallback; 1948 } 1949 } 1950 } catch (RemoteException e) { 1951 mAtm.mController = null; 1952 Watchdog.getInstance().setActivityController(null); 1953 return false; 1954 } 1955 } 1956 if (targetRunnable != null) { 1957 // Execute runnable outside WM lock since the runnable will hold AM lock 1958 targetRunnable.run(); 1959 return true; 1960 } 1961 return false; 1962 } 1963 1964 /** 1965 * Called to notify {@link WindowProcessController} of a started service. 1966 * 1967 * @param serviceInfo information describing the started service. 1968 */ onServiceStarted(ServiceInfo serviceInfo)1969 public void onServiceStarted(ServiceInfo serviceInfo) { 1970 String permission = serviceInfo.permission; 1971 if (permission == null) { 1972 return; 1973 } 1974 1975 // TODO: Audit remaining services for disabling activity override (Wallpaper, Dream, etc). 1976 switch (permission) { 1977 case Manifest.permission.BIND_INPUT_METHOD: 1978 mHasImeService = true; 1979 // Fall-through 1980 case Manifest.permission.BIND_ACCESSIBILITY_SERVICE: 1981 case Manifest.permission.BIND_VOICE_INTERACTION: 1982 // We want to avoid overriding the config of these services with that of the 1983 // activity as it could lead to incorrect display metrics. For ex, IME services 1984 // expect their config to match the config of the display with the IME window 1985 // showing. 1986 // If the configuration has been overridden by previous activity, empty it. 1987 mIsActivityConfigOverrideAllowed = false; 1988 // The call to `onServiceStarted` is not guarded with WM lock. 1989 mAtm.mH.post(() -> { 1990 synchronized (mAtm.mGlobalLock) { 1991 unregisterActivityConfigurationListener(); 1992 } 1993 }); 1994 break; 1995 default: 1996 break; 1997 } 1998 } 1999 2000 /** Returns {@code true} if the process prefers to use fifo scheduling. */ useFifoUiScheduling()2001 public boolean useFifoUiScheduling() { 2002 return mUseFifoUiScheduling; 2003 } 2004 2005 @HotPath(caller = HotPath.OOM_ADJUSTMENT) onTopProcChanged()2006 public void onTopProcChanged() { 2007 if (mAtm.mVrController.isInterestingToSchedGroup()) { 2008 mAtm.mH.post(() -> { 2009 synchronized (mAtm.mGlobalLock) { 2010 mAtm.mVrController.onTopProcChangedLocked(this); 2011 } 2012 }); 2013 } 2014 } 2015 2016 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isHomeProcess()2017 public boolean isHomeProcess() { 2018 return this == mAtm.mHomeProcess; 2019 } 2020 2021 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isShowingUiWhileDozing()2022 public boolean isShowingUiWhileDozing() { 2023 return this == mAtm.mVisibleDozeUiProcess; 2024 } 2025 2026 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isPreviousProcess()2027 public boolean isPreviousProcess() { 2028 return this == mAtm.mPreviousProcess; 2029 } 2030 2031 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isHeavyWeightProcess()2032 public boolean isHeavyWeightProcess() { 2033 return this == mAtm.mHeavyWeightProcess; 2034 } 2035 2036 @HotPath(caller = HotPath.PROCESS_CHANGE) isFactoryTestProcess()2037 public boolean isFactoryTestProcess() { 2038 final int factoryTestMode = mAtm.mFactoryTest; 2039 if (factoryTestMode == FactoryTest.FACTORY_TEST_OFF) { 2040 return false; 2041 } 2042 if (factoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) { 2043 final ComponentName topComponent = mAtm.mTopComponent; 2044 if (topComponent != null && mName.equals(topComponent.getPackageName())) { 2045 return true; 2046 } 2047 } 2048 return factoryTestMode == FactoryTest.FACTORY_TEST_HIGH_LEVEL 2049 && (mInfo.flags & ApplicationInfo.FLAG_FACTORY_TEST) != 0; 2050 } 2051 2052 /** Sets the current stopped state of the app, which is reset as soon as metrics are logged */ setStoppedState(@toppedState int stoppedState)2053 public void setStoppedState(@StoppedState int stoppedState) { 2054 mStoppedState = stoppedState; 2055 } 2056 getWasStoppedLogged()2057 boolean getWasStoppedLogged() { 2058 return mWasStoppedLogged; 2059 } 2060 setWasStoppedLogged(boolean logged)2061 void setWasStoppedLogged(boolean logged) { 2062 mWasStoppedLogged = logged; 2063 } 2064 2065 /** Returns whether the app had been force-stopped before this launch */ wasForceStopped()2066 public boolean wasForceStopped() { 2067 return mStoppedState == STOPPED_STATE_FORCE_STOPPED; 2068 } 2069 2070 /** Returns whether this app is being launched for the first time since install */ wasFirstLaunch()2071 boolean wasFirstLaunch() { 2072 return mStoppedState == STOPPED_STATE_FIRST_LAUNCH; 2073 } 2074 setRunningRemoteAnimation(boolean running)2075 void setRunningRemoteAnimation(boolean running) { 2076 if (running) { 2077 addAnimatingReason(ANIMATING_REASON_REMOTE_ANIMATION); 2078 } else { 2079 removeAnimatingReason(ANIMATING_REASON_REMOTE_ANIMATION); 2080 } 2081 } 2082 addAnimatingReason(@nimatingReason int reason)2083 void addAnimatingReason(@AnimatingReason int reason) { 2084 final int prevReasons = mAnimatingReasons; 2085 mAnimatingReasons |= reason; 2086 if (prevReasons == 0) { 2087 setAnimating(true); 2088 } 2089 } 2090 removeAnimatingReason(@nimatingReason int reason)2091 void removeAnimatingReason(@AnimatingReason int reason) { 2092 final int prevReasons = mAnimatingReasons; 2093 mAnimatingReasons &= ~reason; 2094 if (prevReasons != 0 && mAnimatingReasons == 0) { 2095 setAnimating(false); 2096 } 2097 } 2098 2099 /** Applies the animating state to activity manager for updating process priority. */ setAnimating(boolean animating)2100 private void setAnimating(boolean animating) { 2101 // Posting on handler so WM lock isn't held when we call into AM. 2102 mAtm.mH.post(() -> mListener.setRunningRemoteAnimation(animating)); 2103 } 2104 isRunningRemoteTransition()2105 boolean isRunningRemoteTransition() { 2106 return (mAnimatingReasons & ANIMATING_REASON_REMOTE_ANIMATION) != 0; 2107 } 2108 2109 /** Adjusts scheduling group for animation. This method MUST NOT be called inside WM lock. */ setRunningAnimationUnsafe()2110 void setRunningAnimationUnsafe() { 2111 mListener.setRunningRemoteAnimation(true); 2112 } 2113 2114 @Override toString()2115 public String toString() { 2116 return mOwner != null ? mOwner.toString() : null; 2117 } 2118 dump(PrintWriter pw, String prefix)2119 public void dump(PrintWriter pw, String prefix) { 2120 synchronized (mAtm.mGlobalLock) { 2121 if (mActivities.size() > 0) { 2122 pw.print(prefix); pw.println("Activities:"); 2123 for (int i = 0; i < mActivities.size(); i++) { 2124 pw.print(prefix); pw.print(" - "); pw.println(mActivities.get(i)); 2125 } 2126 } 2127 if (mRemoteActivities != null && !mRemoteActivities.isEmpty()) { 2128 pw.print(prefix); pw.println("Remote Activities:"); 2129 for (int i = mRemoteActivities.size() - 1; i >= 0; i--) { 2130 pw.print(prefix); pw.print(" - "); 2131 pw.print(mRemoteActivities.keyAt(i)); pw.print(" flags="); 2132 final int flags = mRemoteActivities.valueAt(i)[0]; 2133 if ((flags & REMOTE_ACTIVITY_FLAG_HOST_ACTIVITY) != 0) { 2134 pw.print("host "); 2135 } 2136 if ((flags & REMOTE_ACTIVITY_FLAG_EMBEDDED_ACTIVITY) != 0) { 2137 pw.print("embedded"); 2138 } 2139 pw.println(); 2140 } 2141 } 2142 if (mRecentTasks.size() > 0) { 2143 pw.println(prefix + "Recent Tasks:"); 2144 for (int i = 0; i < mRecentTasks.size(); i++) { 2145 pw.println(prefix + " - " + mRecentTasks.get(i)); 2146 } 2147 } 2148 2149 if (mVrThreadTid != 0) { 2150 pw.print(prefix); pw.print("mVrThreadTid="); pw.println(mVrThreadTid); 2151 } 2152 2153 mBgLaunchController.dump(pw, prefix); 2154 } 2155 pw.println(prefix + " Configuration=" + getConfiguration()); 2156 pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration()); 2157 pw.println(prefix + " mLastReportedConfiguration=" + (mHasCachedConfiguration 2158 ? ("(cached) " + mLastReportedConfiguration) : mLastReportedConfiguration)); 2159 2160 final int animatingReasons = mAnimatingReasons; 2161 if (animatingReasons != 0) { 2162 pw.print(prefix + " mAnimatingReasons="); 2163 if ((animatingReasons & ANIMATING_REASON_REMOTE_ANIMATION) != 0) { 2164 pw.print("remote-animation|"); 2165 } 2166 if ((animatingReasons & ANIMATING_REASON_WAKEFULNESS_CHANGE) != 0) { 2167 pw.print("wakefulness|"); 2168 } 2169 pw.println(); 2170 } 2171 if (mUseFifoUiScheduling) { 2172 pw.println(prefix + " mUseFifoUiScheduling=true"); 2173 } 2174 2175 final int stateFlags = mActivityStateFlags; 2176 if (stateFlags != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) { 2177 pw.print(prefix + " mActivityStateFlags="); 2178 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE) != 0) { 2179 pw.print("W|"); 2180 } 2181 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) { 2182 pw.print("V|"); 2183 if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_RESUMED) != 0) { 2184 pw.print("R|"); 2185 if ((stateFlags & ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN) != 0) { 2186 pw.print("RS|"); 2187 } 2188 if ((stateFlags & ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0) { 2189 pw.print("PF|"); 2190 } 2191 } 2192 } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) { 2193 pw.print("P|"); 2194 } else if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) { 2195 pw.print("S|"); 2196 if ((stateFlags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0) { 2197 pw.print("F|"); 2198 } 2199 } 2200 if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0) { 2201 pw.print("VT|"); 2202 } 2203 final int taskLayer = stateFlags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; 2204 if (taskLayer != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) { 2205 pw.print("taskLayer=" + taskLayer); 2206 } 2207 pw.println(); 2208 } 2209 } 2210 dumpDebug(ProtoOutputStream proto, long fieldId)2211 void dumpDebug(ProtoOutputStream proto, long fieldId) { 2212 mListener.dumpDebug(proto, fieldId); 2213 } 2214 2215 @Override setOverrideGender(Configuration requestsTmpConfig, int gender)2216 protected boolean setOverrideGender(Configuration requestsTmpConfig, int gender) { 2217 return applyConfigGenderOverride(requestsTmpConfig, gender, 2218 mAtm.mGrammaticalManagerInternal, mUid); 2219 } 2220 applyConfigGenderOverride(@onNull Configuration overrideConfig, @Configuration.GrammaticalGender int override, GrammaticalInflectionManagerInternal service, int uid)2221 static boolean applyConfigGenderOverride(@NonNull Configuration overrideConfig, 2222 @Configuration.GrammaticalGender int override, 2223 GrammaticalInflectionManagerInternal service, int uid) { 2224 final boolean canGetSystemValue = service != null 2225 && service.canGetSystemGrammaticalGender(uid); 2226 2227 // The priority here is as follows: 2228 // - app-specific override if set 2229 // - system value if allowed to see it 2230 // - global configuration otherwise 2231 final int targetValue = (override != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) 2232 ? override 2233 : canGetSystemValue 2234 ? Configuration.GRAMMATICAL_GENDER_UNDEFINED 2235 : service != null 2236 ? service.getGrammaticalGenderFromDeveloperSettings() 2237 : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED; 2238 if (overrideConfig.getGrammaticalGenderRaw() == targetValue) { 2239 return false; 2240 } 2241 overrideConfig.setGrammaticalGender(targetValue); 2242 return true; 2243 } 2244 } 2245