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.os.Build.VERSION_CODES.Q; 22 import static android.view.Display.INVALID_DISPLAY; 23 24 import static com.android.server.am.ActivityManagerService.MY_PID; 25 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; 26 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; 27 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; 28 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; 29 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; 30 import static com.android.server.wm.ActivityStack.ActivityState.STARTED; 31 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING; 32 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS; 33 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; 34 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; 35 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; 36 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; 37 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 39 import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS; 40 import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS; 41 import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS; 42 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; 43 44 import android.Manifest; 45 import android.annotation.NonNull; 46 import android.annotation.Nullable; 47 import android.app.ActivityManager; 48 import android.app.ActivityThread; 49 import android.app.IApplicationThread; 50 import android.app.ProfilerInfo; 51 import android.app.servertransaction.ConfigurationChangeItem; 52 import android.content.Context; 53 import android.content.Intent; 54 import android.content.pm.ActivityInfo; 55 import android.content.pm.ApplicationInfo; 56 import android.content.pm.ServiceInfo; 57 import android.content.res.Configuration; 58 import android.os.Build; 59 import android.os.Message; 60 import android.os.Process; 61 import android.os.RemoteException; 62 import android.os.SystemClock; 63 import android.util.ArraySet; 64 import android.util.Log; 65 import android.util.Slog; 66 import android.util.proto.ProtoOutputStream; 67 import android.view.IRemoteAnimationRunner; 68 69 import com.android.internal.annotations.VisibleForTesting; 70 import com.android.internal.app.HeavyWeightSwitcherActivity; 71 import com.android.internal.util.function.pooled.PooledLambda; 72 import com.android.server.Watchdog; 73 import com.android.server.wm.ActivityTaskManagerService.HotPath; 74 75 import java.io.IOException; 76 import java.io.PrintWriter; 77 import java.util.ArrayList; 78 import java.util.List; 79 80 /** 81 * The Activity Manager (AM) package manages the lifecycle of processes in the system through 82 * ProcessRecord. However, it is important for the Window Manager (WM) package to be aware 83 * of the processes and their state since it affects how WM manages windows and activities. This 84 * class that allows the ProcessRecord object in the AM package to communicate important 85 * changes to its state to the WM package in a structured way. WM package also uses 86 * {@link WindowProcessListener} to request changes to the process state on the AM side. 87 * Note that public calls into this class are assumed to be originating from outside the 88 * window manager so the window manager lock is held and appropriate permissions are checked before 89 * calls are allowed to proceed. 90 */ 91 public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer> 92 implements ConfigurationContainerListener { 93 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM; 94 private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; 95 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; 96 97 // all about the first app in the process 98 final ApplicationInfo mInfo; 99 final String mName; 100 final int mUid; 101 // The process of this application; 0 if none 102 private volatile int mPid; 103 // user of process. 104 final int mUserId; 105 // The owner of this window process controller object. Mainly for identification when we 106 // communicate back to the activity manager side. 107 public final Object mOwner; 108 // List of packages running in the process 109 final ArraySet<String> mPkgList = new ArraySet<>(); 110 private final WindowProcessListener mListener; 111 private final ActivityTaskManagerService mAtm; 112 // The actual proc... may be null only if 'persistent' is true (in which case we are in the 113 // process of launching the app) 114 private IApplicationThread mThread; 115 // Currently desired scheduling class 116 private volatile int mCurSchedGroup; 117 // Currently computed process state 118 private volatile int mCurProcState = PROCESS_STATE_NONEXISTENT; 119 // Last reported process state; 120 private volatile int mRepProcState = PROCESS_STATE_NONEXISTENT; 121 // are we in the process of crashing? 122 private volatile boolean mCrashing; 123 // does the app have a not responding dialog? 124 private volatile boolean mNotResponding; 125 // always keep this application running? 126 private volatile boolean mPersistent; 127 // The ABI this process was launched with 128 private volatile String mRequiredAbi; 129 // Running any services that are foreground? 130 private volatile boolean mHasForegroundServices; 131 // Running any activities that are foreground? 132 private volatile boolean mHasForegroundActivities; 133 // Are there any client services with activities? 134 private volatile boolean mHasClientActivities; 135 // Is this process currently showing a non-activity UI that the user is interacting with? 136 // E.g. The status bar when it is expanded, but not when it is minimized. When true the process 137 // will be set to use the ProcessList#SCHED_GROUP_TOP_APP scheduling group to boost performance. 138 private volatile boolean mHasTopUi; 139 // Is the process currently showing a non-activity UI that overlays on-top of activity UIs on 140 // screen. E.g. display a window of type 141 // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY When true the process will 142 // oom adj score will be set to ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance 143 // of the process getting killed. 144 private volatile boolean mHasOverlayUi; 145 // Want to clean up resources from showing UI? 146 private volatile boolean mPendingUiClean; 147 // The time we sent the last interaction event 148 private volatile long mInteractionEventTime; 149 // When we became foreground for interaction purposes 150 private volatile long mFgInteractionTime; 151 // When (uptime) the process last became unimportant 152 private volatile long mWhenUnimportant; 153 // was app launched for debugging? 154 private volatile boolean mDebugging; 155 // Active instrumentation running in process? 156 private volatile boolean mInstrumenting; 157 // Active instrumentation with background activity starts privilege running in process? 158 private volatile boolean mInstrumentingWithBackgroundActivityStartPrivileges; 159 // This process it perceptible by the user. 160 private volatile boolean mPerceptible; 161 // Set to true when process was launched with a wrapper attached 162 private volatile boolean mUsingWrapper; 163 // Set to true if this process is currently temporarily whitelisted to start activities even if 164 // it's not in the foreground 165 private volatile boolean mAllowBackgroundActivityStarts; 166 // Set of UIDs of clients currently bound to this process 167 private volatile ArraySet<Integer> mBoundClientUids = new ArraySet<Integer>(); 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 // all activities running in the process 176 private final ArrayList<ActivityRecord> mActivities = new ArrayList<>(); 177 // any tasks this process had run root activities in 178 private final ArrayList<Task> mRecentTasks = new ArrayList<>(); 179 // The most recent top-most activity that was resumed in the process for pre-Q app. 180 private ActivityRecord mPreQTopResumedActivity = null; 181 // The last time an activity was launched in the process 182 private long mLastActivityLaunchTime; 183 // The last time an activity was finished in the process while the process participated 184 // in a visible task 185 private long mLastActivityFinishTime; 186 187 // Last configuration that was reported to the process. 188 private final Configuration mLastReportedConfiguration = new Configuration(); 189 // Configuration that is waiting to be dispatched to the process. 190 private Configuration mPendingConfiguration; 191 private final Configuration mNewOverrideConfig = new Configuration(); 192 // Registered display id as a listener to override config change 193 private int mDisplayId; 194 private ActivityRecord mConfigActivityRecord; 195 // Whether the activity config override is allowed for this process. 196 private volatile boolean mIsActivityConfigOverrideAllowed = true; 197 /** 198 * Activities that hosts some UI drawn by the current process. The activities live 199 * in another process. This is used to check if the process is currently showing anything 200 * visible to the user. 201 */ 202 @Nullable 203 private final ArrayList<ActivityRecord> mHostActivities = new ArrayList<>(); 204 205 /** Whether our process is currently running a {@link RecentsAnimation} */ 206 private boolean mRunningRecentsAnimation; 207 208 /** Whether our process is currently running a {@link IRemoteAnimationRunner} */ 209 private boolean mRunningRemoteAnimation; 210 WindowProcessController(@onNull ActivityTaskManagerService atm, ApplicationInfo info, String name, int uid, int userId, Object owner, WindowProcessListener listener)211 public WindowProcessController(@NonNull ActivityTaskManagerService atm, ApplicationInfo info, 212 String name, int uid, int userId, Object owner, WindowProcessListener listener) { 213 mInfo = info; 214 mName = name; 215 mUid = uid; 216 mUserId = userId; 217 mOwner = owner; 218 mListener = listener; 219 mAtm = atm; 220 mDisplayId = INVALID_DISPLAY; 221 222 boolean isSysUiPackage = info.packageName.equals( 223 mAtm.getSysUiServiceComponentLocked().getPackageName()); 224 if (isSysUiPackage || mUid == Process.SYSTEM_UID) { 225 // This is a system owned process and should not use an activity config. 226 // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs. 227 mIsActivityConfigOverrideAllowed = false; 228 } 229 230 onConfigurationChanged(atm.getGlobalConfiguration()); 231 } 232 setPid(int pid)233 public void setPid(int pid) { 234 mPid = pid; 235 } 236 getPid()237 public int getPid() { 238 return mPid; 239 } 240 241 @HotPath(caller = HotPath.PROCESS_CHANGE) setThread(IApplicationThread thread)242 public void setThread(IApplicationThread thread) { 243 synchronized (mAtm.mGlobalLockWithoutBoost) { 244 mThread = thread; 245 // In general this is called from attaching application, so the last configuration 246 // has been sent to client by {@link android.app.IApplicationThread#bindApplication}. 247 // If this process is system server, it is fine because system is booting and a new 248 // configuration will update when display is ready. 249 if (thread != null) { 250 setLastReportedConfiguration(getConfiguration()); 251 } 252 } 253 } 254 getThread()255 IApplicationThread getThread() { 256 return mThread; 257 } 258 hasThread()259 boolean hasThread() { 260 return mThread != null; 261 } 262 setCurrentSchedulingGroup(int curSchedGroup)263 public void setCurrentSchedulingGroup(int curSchedGroup) { 264 mCurSchedGroup = curSchedGroup; 265 } 266 getCurrentSchedulingGroup()267 int getCurrentSchedulingGroup() { 268 return mCurSchedGroup; 269 } 270 setCurrentProcState(int curProcState)271 public void setCurrentProcState(int curProcState) { 272 mCurProcState = curProcState; 273 } 274 getCurrentProcState()275 int getCurrentProcState() { 276 return mCurProcState; 277 } 278 setReportedProcState(int repProcState)279 public void setReportedProcState(int repProcState) { 280 mRepProcState = repProcState; 281 } 282 getReportedProcState()283 int getReportedProcState() { 284 return mRepProcState; 285 } 286 setCrashing(boolean crashing)287 public void setCrashing(boolean crashing) { 288 mCrashing = crashing; 289 } 290 isCrashing()291 boolean isCrashing() { 292 return mCrashing; 293 } 294 setNotResponding(boolean notResponding)295 public void setNotResponding(boolean notResponding) { 296 mNotResponding = notResponding; 297 } 298 isNotResponding()299 boolean isNotResponding() { 300 return mNotResponding; 301 } 302 setPersistent(boolean persistent)303 public void setPersistent(boolean persistent) { 304 mPersistent = persistent; 305 } 306 isPersistent()307 boolean isPersistent() { 308 return mPersistent; 309 } 310 setHasForegroundServices(boolean hasForegroundServices)311 public void setHasForegroundServices(boolean hasForegroundServices) { 312 mHasForegroundServices = hasForegroundServices; 313 } 314 hasForegroundServices()315 boolean hasForegroundServices() { 316 return mHasForegroundServices; 317 } 318 setHasForegroundActivities(boolean hasForegroundActivities)319 public void setHasForegroundActivities(boolean hasForegroundActivities) { 320 mHasForegroundActivities = hasForegroundActivities; 321 } 322 hasForegroundActivities()323 boolean hasForegroundActivities() { 324 return mHasForegroundActivities; 325 } 326 setHasClientActivities(boolean hasClientActivities)327 public void setHasClientActivities(boolean hasClientActivities) { 328 mHasClientActivities = hasClientActivities; 329 } 330 hasClientActivities()331 boolean hasClientActivities() { 332 return mHasClientActivities; 333 } 334 setHasTopUi(boolean hasTopUi)335 public void setHasTopUi(boolean hasTopUi) { 336 mHasTopUi = hasTopUi; 337 } 338 hasTopUi()339 boolean hasTopUi() { 340 return mHasTopUi; 341 } 342 setHasOverlayUi(boolean hasOverlayUi)343 public void setHasOverlayUi(boolean hasOverlayUi) { 344 mHasOverlayUi = hasOverlayUi; 345 } 346 hasOverlayUi()347 boolean hasOverlayUi() { 348 return mHasOverlayUi; 349 } 350 setPendingUiClean(boolean hasPendingUiClean)351 public void setPendingUiClean(boolean hasPendingUiClean) { 352 mPendingUiClean = hasPendingUiClean; 353 } 354 hasPendingUiClean()355 boolean hasPendingUiClean() { 356 return mPendingUiClean; 357 } 358 359 /** @return {@code true} if the process registered to a display as a config listener. */ registeredForDisplayConfigChanges()360 boolean registeredForDisplayConfigChanges() { 361 return mDisplayId != INVALID_DISPLAY; 362 } 363 364 /** @return {@code true} if the process registered to an activity as a config listener. */ 365 @VisibleForTesting registeredForActivityConfigChanges()366 boolean registeredForActivityConfigChanges() { 367 return mConfigActivityRecord != null; 368 } 369 postPendingUiCleanMsg(boolean pendingUiClean)370 void postPendingUiCleanMsg(boolean pendingUiClean) { 371 if (mListener == null) return; 372 // Posting on handler so WM lock isn't held when we call into AM. 373 final Message m = PooledLambda.obtainMessage( 374 WindowProcessListener::setPendingUiClean, mListener, pendingUiClean); 375 mAtm.mH.sendMessage(m); 376 } 377 setInteractionEventTime(long interactionEventTime)378 public void setInteractionEventTime(long interactionEventTime) { 379 mInteractionEventTime = interactionEventTime; 380 } 381 getInteractionEventTime()382 long getInteractionEventTime() { 383 return mInteractionEventTime; 384 } 385 setFgInteractionTime(long fgInteractionTime)386 public void setFgInteractionTime(long fgInteractionTime) { 387 mFgInteractionTime = fgInteractionTime; 388 } 389 getFgInteractionTime()390 long getFgInteractionTime() { 391 return mFgInteractionTime; 392 } 393 setWhenUnimportant(long whenUnimportant)394 public void setWhenUnimportant(long whenUnimportant) { 395 mWhenUnimportant = whenUnimportant; 396 } 397 getWhenUnimportant()398 long getWhenUnimportant() { 399 return mWhenUnimportant; 400 } 401 setRequiredAbi(String requiredAbi)402 public void setRequiredAbi(String requiredAbi) { 403 mRequiredAbi = requiredAbi; 404 } 405 getRequiredAbi()406 String getRequiredAbi() { 407 return mRequiredAbi; 408 } 409 410 /** Returns ID of display overriding the configuration for this process, or 411 * INVALID_DISPLAY if no display is overriding. */ 412 @VisibleForTesting getDisplayId()413 int getDisplayId() { 414 return mDisplayId; 415 } 416 setDebugging(boolean debugging)417 public void setDebugging(boolean debugging) { 418 mDebugging = debugging; 419 } 420 isDebugging()421 boolean isDebugging() { 422 return mDebugging; 423 } 424 setUsingWrapper(boolean usingWrapper)425 public void setUsingWrapper(boolean usingWrapper) { 426 mUsingWrapper = usingWrapper; 427 } 428 isUsingWrapper()429 boolean isUsingWrapper() { 430 return mUsingWrapper; 431 } 432 setLastActivityLaunchTime(long launchTime)433 void setLastActivityLaunchTime(long launchTime) { 434 if (launchTime <= mLastActivityLaunchTime) { 435 if (launchTime < mLastActivityLaunchTime) { 436 Slog.w(TAG, 437 "Tried to set launchTime (" + launchTime + ") < mLastActivityLaunchTime (" 438 + mLastActivityLaunchTime + ")"); 439 } 440 return; 441 } 442 mLastActivityLaunchTime = launchTime; 443 } 444 setLastActivityFinishTimeIfNeeded(long finishTime)445 void setLastActivityFinishTimeIfNeeded(long finishTime) { 446 if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) { 447 return; 448 } 449 mLastActivityFinishTime = finishTime; 450 } 451 setAllowBackgroundActivityStarts(boolean allowBackgroundActivityStarts)452 public void setAllowBackgroundActivityStarts(boolean allowBackgroundActivityStarts) { 453 mAllowBackgroundActivityStarts = allowBackgroundActivityStarts; 454 } 455 areBackgroundActivityStartsAllowed()456 boolean areBackgroundActivityStartsAllowed() { 457 // allow if the whitelisting flag was explicitly set 458 if (mAllowBackgroundActivityStarts) { 459 if (DEBUG_ACTIVITY_STARTS) { 460 Slog.d(TAG, "[WindowProcessController(" + mPid 461 + ")] Activity start allowed: mAllowBackgroundActivityStarts = true"); 462 } 463 return true; 464 } 465 // allow if any activity in the caller has either started or finished very recently, and 466 // it must be started or finished after last stop app switches time. 467 final long now = SystemClock.uptimeMillis(); 468 if (now - mLastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS 469 || now - mLastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) { 470 // if activity is started and finished before stop app switch time, we should not 471 // let app to be able to start background activity even it's in grace period. 472 if (mLastActivityLaunchTime > mAtm.getLastStopAppSwitchesTime() 473 || mLastActivityFinishTime > mAtm.getLastStopAppSwitchesTime()) { 474 if (DEBUG_ACTIVITY_STARTS) { 475 Slog.d(TAG, "[WindowProcessController(" + mPid 476 + ")] Activity start allowed: within " 477 + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period"); 478 } 479 return true; 480 } 481 if (DEBUG_ACTIVITY_STARTS) { 482 Slog.d(TAG, "[WindowProcessController(" + mPid + ")] Activity start within " 483 + ACTIVITY_BG_START_GRACE_PERIOD_MS 484 + "ms grace period but also within stop app switch window"); 485 } 486 487 } 488 // allow if the proc is instrumenting with background activity starts privs 489 if (mInstrumentingWithBackgroundActivityStartPrivileges) { 490 if (DEBUG_ACTIVITY_STARTS) { 491 Slog.d(TAG, "[WindowProcessController(" + mPid 492 + ")] Activity start allowed: process instrumenting with background " 493 + "activity starts privileges"); 494 } 495 return true; 496 } 497 // allow if the caller has an activity in any foreground task 498 if (hasActivityInVisibleTask()) { 499 if (DEBUG_ACTIVITY_STARTS) { 500 Slog.d(TAG, "[WindowProcessController(" + mPid 501 + ")] Activity start allowed: process has activity in foreground task"); 502 } 503 return true; 504 } 505 // allow if the caller is bound by a UID that's currently foreground 506 if (isBoundByForegroundUid()) { 507 if (DEBUG_ACTIVITY_STARTS) { 508 Slog.d(TAG, "[WindowProcessController(" + mPid 509 + ")] Activity start allowed: process bound by foreground uid"); 510 } 511 return true; 512 } 513 return false; 514 } 515 isBoundByForegroundUid()516 private boolean isBoundByForegroundUid() { 517 for (int i = mBoundClientUids.size() - 1; i >= 0; --i) { 518 if (mAtm.isUidForeground(mBoundClientUids.valueAt(i))) { 519 return true; 520 } 521 } 522 return false; 523 } 524 setBoundClientUids(ArraySet<Integer> boundClientUids)525 public void setBoundClientUids(ArraySet<Integer> boundClientUids) { 526 mBoundClientUids = boundClientUids; 527 } 528 setInstrumenting(boolean instrumenting, boolean hasBackgroundActivityStartPrivileges)529 public void setInstrumenting(boolean instrumenting, 530 boolean hasBackgroundActivityStartPrivileges) { 531 mInstrumenting = instrumenting; 532 mInstrumentingWithBackgroundActivityStartPrivileges = hasBackgroundActivityStartPrivileges; 533 } 534 isInstrumenting()535 boolean isInstrumenting() { 536 return mInstrumenting; 537 } 538 setPerceptible(boolean perceptible)539 public void setPerceptible(boolean perceptible) { 540 mPerceptible = perceptible; 541 } 542 isPerceptible()543 boolean isPerceptible() { 544 return mPerceptible; 545 } 546 547 @Override getChildCount()548 protected int getChildCount() { 549 return 0; 550 } 551 552 @Override getChildAt(int index)553 protected ConfigurationContainer getChildAt(int index) { 554 return null; 555 } 556 557 @Override getParent()558 protected ConfigurationContainer getParent() { 559 // Returning RootWindowContainer as the parent, so that this process controller always 560 // has full configuration and overrides (e.g. from display) are always added on top of 561 // global config. 562 return mAtm.mRootWindowContainer; 563 } 564 565 @HotPath(caller = HotPath.PROCESS_CHANGE) addPackage(String packageName)566 public void addPackage(String packageName) { 567 synchronized (mAtm.mGlobalLockWithoutBoost) { 568 mPkgList.add(packageName); 569 } 570 } 571 572 @HotPath(caller = HotPath.PROCESS_CHANGE) clearPackageList()573 public void clearPackageList() { 574 synchronized (mAtm.mGlobalLockWithoutBoost) { 575 mPkgList.clear(); 576 } 577 } 578 addActivityIfNeeded(ActivityRecord r)579 void addActivityIfNeeded(ActivityRecord r) { 580 // even if we already track this activity, note down that it has been launched 581 setLastActivityLaunchTime(r.lastLaunchTime); 582 if (mActivities.contains(r)) { 583 return; 584 } 585 mActivities.add(r); 586 updateActivityConfigurationListener(); 587 } 588 removeActivity(ActivityRecord r)589 void removeActivity(ActivityRecord r) { 590 mActivities.remove(r); 591 updateActivityConfigurationListener(); 592 } 593 makeFinishingForProcessRemoved()594 void makeFinishingForProcessRemoved() { 595 for (int i = mActivities.size() - 1; i >= 0; --i) { 596 mActivities.get(i).makeFinishingLocked(); 597 } 598 } 599 clearActivities()600 void clearActivities() { 601 mActivities.clear(); 602 updateActivityConfigurationListener(); 603 } 604 605 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasActivities()606 public boolean hasActivities() { 607 synchronized (mAtm.mGlobalLockWithoutBoost) { 608 return !mActivities.isEmpty(); 609 } 610 } 611 612 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasVisibleActivities()613 public boolean hasVisibleActivities() { 614 synchronized (mAtm.mGlobalLockWithoutBoost) { 615 for (int i = mActivities.size() - 1; i >= 0; --i) { 616 final ActivityRecord r = mActivities.get(i); 617 if (r.mVisibleRequested) { 618 return true; 619 } 620 } 621 } 622 return false; 623 } 624 625 @HotPath(caller = HotPath.LRU_UPDATE) hasActivitiesOrRecentTasks()626 public boolean hasActivitiesOrRecentTasks() { 627 synchronized (mAtm.mGlobalLockWithoutBoost) { 628 return !mActivities.isEmpty() || !mRecentTasks.isEmpty(); 629 } 630 } 631 hasActivityInVisibleTask()632 private boolean hasActivityInVisibleTask() { 633 for (int i = mActivities.size() - 1; i >= 0; --i) { 634 Task task = mActivities.get(i).getTask(); 635 if (task == null) { 636 continue; 637 } 638 ActivityRecord topActivity = task.getTopNonFinishingActivity(); 639 if (topActivity != null && topActivity.mVisibleRequested) { 640 return true; 641 } 642 } 643 return false; 644 } 645 646 /** 647 * Update the top resuming activity in process for pre-Q apps, only the top-most visible 648 * activities are allowed to be resumed per process. 649 * @return {@code true} if the activity is allowed to be resumed by compatibility 650 * restrictions, which the activity was the topmost visible activity in process or the app is 651 * targeting after Q. Note that non-focusable activity, in picture-in-picture mode for instance, 652 * does not count as a topmost activity. 653 */ updateTopResumingActivityInProcessIfNeeded(@onNull ActivityRecord activity)654 boolean updateTopResumingActivityInProcessIfNeeded(@NonNull ActivityRecord activity) { 655 if (mInfo.targetSdkVersion >= Q || mPreQTopResumedActivity == activity) { 656 return true; 657 } 658 659 final DisplayContent display = activity.getDisplay(); 660 if (display == null) { 661 // No need to update if the activity hasn't attach to any display. 662 return false; 663 } 664 665 boolean canUpdate = false; 666 final DisplayContent topDisplay = 667 mPreQTopResumedActivity != null ? mPreQTopResumedActivity.getDisplay() : null; 668 // Update the topmost activity if current top activity is 669 // - not on any display OR 670 // - no longer visible OR 671 // - not focusable (in PiP mode for instance) 672 if (topDisplay == null 673 || !mPreQTopResumedActivity.mVisibleRequested 674 || !mPreQTopResumedActivity.isFocusable()) { 675 canUpdate = true; 676 } 677 678 // Update the topmost activity if the current top activity wasn't on top of the other one. 679 if (!canUpdate && topDisplay.mDisplayContent.compareTo(display.mDisplayContent) < 0) { 680 canUpdate = true; 681 } 682 683 // Compare the z-order of ActivityStacks if both activities landed on same display. 684 if (display == topDisplay 685 && mPreQTopResumedActivity.getRootTask().compareTo( 686 activity.getRootTask()) <= 0) { 687 canUpdate = true; 688 } 689 690 if (canUpdate) { 691 // Make sure the previous top activity in the process no longer be resumed. 692 if (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isState(RESUMED)) { 693 final ActivityStack stack = mPreQTopResumedActivity.getRootTask(); 694 if (stack != null) { 695 stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, 696 activity); 697 } 698 } 699 mPreQTopResumedActivity = activity; 700 } 701 return canUpdate; 702 } 703 stopFreezingActivities()704 public void stopFreezingActivities() { 705 synchronized (mAtm.mGlobalLock) { 706 int i = mActivities.size(); 707 while (i > 0) { 708 i--; 709 mActivities.get(i).stopFreezingScreenLocked(true); 710 } 711 } 712 } 713 finishActivities()714 void finishActivities() { 715 ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities); 716 for (int i = 0; i < activities.size(); i++) { 717 final ActivityRecord r = activities.get(i); 718 if (!r.finishing && r.isInStackLocked()) { 719 r.finishIfPossible("finish-heavy", true /* oomAdj */); 720 } 721 } 722 } 723 isInterestingToUser()724 public boolean isInterestingToUser() { 725 synchronized (mAtm.mGlobalLock) { 726 final int size = mActivities.size(); 727 for (int i = 0; i < size; i++) { 728 ActivityRecord r = mActivities.get(i); 729 if (r.isInterestingToUserLocked()) { 730 return true; 731 } 732 } 733 if (isEmbedded()) { 734 return true; 735 } 736 } 737 return false; 738 } 739 740 /** 741 * @return {@code true} if this process is rendering content on to a window shown by 742 * another process. 743 */ isEmbedded()744 private boolean isEmbedded() { 745 for (int i = mHostActivities.size() - 1; i >= 0; --i) { 746 final ActivityRecord r = mHostActivities.get(i); 747 if (r.isInterestingToUserLocked()) { 748 return true; 749 } 750 } 751 return false; 752 } 753 hasRunningActivity(String packageName)754 public boolean hasRunningActivity(String packageName) { 755 synchronized (mAtm.mGlobalLock) { 756 for (int i = mActivities.size() - 1; i >= 0; --i) { 757 final ActivityRecord r = mActivities.get(i); 758 if (packageName.equals(r.packageName)) { 759 return true; 760 } 761 } 762 } 763 return false; 764 } 765 clearPackagePreferredForHomeActivities()766 public void clearPackagePreferredForHomeActivities() { 767 synchronized (mAtm.mGlobalLock) { 768 for (int i = mActivities.size() - 1; i >= 0; --i) { 769 final ActivityRecord r = mActivities.get(i); 770 if (r.isActivityTypeHome()) { 771 Log.i(TAG, "Clearing package preferred activities from " + r.packageName); 772 try { 773 ActivityThread.getPackageManager() 774 .clearPackagePreferredActivities(r.packageName); 775 } catch (RemoteException c) { 776 // pm is in same process, this will never happen. 777 } 778 } 779 } 780 } 781 } 782 hasStartedActivity(ActivityRecord launchedActivity)783 boolean hasStartedActivity(ActivityRecord launchedActivity) { 784 for (int i = mActivities.size() - 1; i >= 0; i--) { 785 final ActivityRecord activity = mActivities.get(i); 786 if (launchedActivity == activity) { 787 continue; 788 } 789 if (!activity.stopped) { 790 return true; 791 } 792 } 793 return false; 794 } 795 hasResumedActivity()796 boolean hasResumedActivity() { 797 for (int i = mActivities.size() - 1; i >= 0; --i) { 798 final ActivityRecord activity = mActivities.get(i); 799 if (activity.isState(RESUMED)) { 800 return true; 801 } 802 } 803 return false; 804 } 805 806 updateIntentForHeavyWeightActivity(Intent intent)807 void updateIntentForHeavyWeightActivity(Intent intent) { 808 if (mActivities.isEmpty()) { 809 return; 810 } 811 ActivityRecord hist = mActivities.get(0); 812 intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName); 813 intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().mTaskId); 814 } 815 shouldKillProcessForRemovedTask(Task task)816 boolean shouldKillProcessForRemovedTask(Task task) { 817 for (int k = 0; k < mActivities.size(); k++) { 818 final ActivityRecord activity = mActivities.get(k); 819 if (!activity.stopped) { 820 // Don't kill process(es) that has an activity not stopped. 821 return false; 822 } 823 final Task otherTask = activity.getTask(); 824 if (task.mTaskId != otherTask.mTaskId && otherTask.inRecents) { 825 // Don't kill process(es) that has an activity in a different task that is 826 // also in recents. 827 return false; 828 } 829 } 830 return true; 831 } 832 releaseSomeActivities(String reason)833 void releaseSomeActivities(String reason) { 834 // Examine all activities currently running in the process. 835 // Candidate activities that can be destroyed. 836 ArrayList<ActivityRecord> candidates = null; 837 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + this); 838 for (int i = 0; i < mActivities.size(); i++) { 839 final ActivityRecord r = mActivities.get(i); 840 // First, if we find an activity that is in the process of being destroyed, 841 // then we just aren't going to do anything for now; we want things to settle 842 // down before we try to prune more activities. 843 if (r.finishing || r.isState(DESTROYING, DESTROYED)) { 844 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r); 845 return; 846 } 847 // Don't consider any activities that are currently not in a state where they 848 // can be destroyed. 849 if (r.mVisibleRequested || !r.stopped || !r.hasSavedState() || !r.isDestroyable() 850 || r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING)) { 851 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r); 852 continue; 853 } 854 855 if (r.getParent() != null) { 856 if (candidates == null) { 857 candidates = new ArrayList<>(); 858 } 859 candidates.add(r); 860 } 861 } 862 863 if (candidates != null) { 864 // Sort based on z-order in hierarchy. 865 candidates.sort(WindowContainer::compareTo); 866 // Release some older activities 867 int maxRelease = Math.max(candidates.size(), 1); 868 do { 869 final ActivityRecord r = candidates.remove(0); 870 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + r 871 + " in state " + r.getState() + " for reason " + reason); 872 r.destroyImmediately(true /*removeFromApp*/, reason); 873 --maxRelease; 874 } while (maxRelease > 0); 875 } 876 } 877 878 /** 879 * Returns display UI context list which there is any app window shows or starting activities 880 * int this process. 881 */ getDisplayContextsWithErrorDialogs(List<Context> displayContexts)882 public void getDisplayContextsWithErrorDialogs(List<Context> displayContexts) { 883 if (displayContexts == null) { 884 return; 885 } 886 synchronized (mAtm.mGlobalLock) { 887 final RootWindowContainer root = mAtm.mWindowManager.mRoot; 888 root.getDisplayContextsWithNonToastVisibleWindows(mPid, displayContexts); 889 890 for (int i = mActivities.size() - 1; i >= 0; --i) { 891 final ActivityRecord r = mActivities.get(i); 892 final int displayId = r.getDisplayId(); 893 final Context c = root.getDisplayUiContext(displayId); 894 895 if (r.mVisibleRequested && !displayContexts.contains(c)) { 896 displayContexts.add(c); 897 } 898 } 899 } 900 } 901 902 /** Adds an activity that hosts UI drawn by the current process. */ addHostActivity(ActivityRecord r)903 void addHostActivity(ActivityRecord r) { 904 if (mHostActivities.contains(r)) { 905 return; 906 } 907 mHostActivities.add(r); 908 } 909 910 /** Removes an activity that hosts UI drawn by the current process. */ removeHostActivity(ActivityRecord r)911 void removeHostActivity(ActivityRecord r) { 912 mHostActivities.remove(r); 913 } 914 915 public interface ComputeOomAdjCallback { onVisibleActivity()916 void onVisibleActivity(); onPausedActivity()917 void onPausedActivity(); onStoppingActivity(boolean finishing)918 void onStoppingActivity(boolean finishing); onOtherActivity()919 void onOtherActivity(); 920 } 921 922 @HotPath(caller = HotPath.OOM_ADJUSTMENT) computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback)923 public int computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback) { 924 // Since there could be more than one activities in a process record, we don't need to 925 // compute the OomAdj with each of them, just need to find out the activity with the 926 // "best" state, the order would be visible, pausing, stopping... 927 ActivityStack.ActivityState best = DESTROYED; 928 boolean finishing = true; 929 boolean visible = false; 930 synchronized (mAtm.mGlobalLockWithoutBoost) { 931 final int activitiesSize = mActivities.size(); 932 for (int j = 0; j < activitiesSize; j++) { 933 final ActivityRecord r = mActivities.get(j); 934 if (r.app != this) { 935 Log.e(TAG, "Found activity " + r + " in proc activity list using " + r.app 936 + " instead of expected " + this); 937 if (r.app == null || (r.app.mUid == mUid)) { 938 // Only fix things up when they look sane 939 r.setProcess(this); 940 } else { 941 continue; 942 } 943 } 944 if (r.mVisibleRequested) { 945 final Task task = r.getTask(); 946 if (task != null && minTaskLayer > 0) { 947 final int layer = task.mLayerRank; 948 if (layer >= 0 && minTaskLayer > layer) { 949 minTaskLayer = layer; 950 } 951 } 952 visible = true; 953 // continue the loop, in case there are multiple visible activities in 954 // this process, we'd find out the one with the minimal layer, thus it'll 955 // get a higher adj score. 956 } else { 957 if (best != PAUSING && best != PAUSED) { 958 if (r.isState(PAUSING, PAUSED)) { 959 best = PAUSING; 960 } else if (r.isState(STOPPING)) { 961 best = STOPPING; 962 // Not "finishing" if any of activity isn't finishing. 963 finishing &= r.finishing; 964 } 965 } 966 } 967 } 968 } 969 if (visible) { 970 callback.onVisibleActivity(); 971 } else if (best == PAUSING) { 972 callback.onPausedActivity(); 973 } else if (best == STOPPING) { 974 callback.onStoppingActivity(finishing); 975 } else { 976 callback.onOtherActivity(); 977 } 978 979 return minTaskLayer; 980 } 981 computeRelaunchReason()982 public int computeRelaunchReason() { 983 synchronized (mAtm.mGlobalLock) { 984 final int activitiesSize = mActivities.size(); 985 for (int i = activitiesSize - 1; i >= 0; i--) { 986 final ActivityRecord r = mActivities.get(i); 987 if (r.mRelaunchReason != RELAUNCH_REASON_NONE) { 988 return r.mRelaunchReason; 989 } 990 } 991 } 992 return RELAUNCH_REASON_NONE; 993 } 994 getInputDispatchingTimeout()995 public long getInputDispatchingTimeout() { 996 synchronized (mAtm.mGlobalLock) { 997 return isInstrumenting() || isUsingWrapper() 998 ? INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS : KEY_DISPATCHING_TIMEOUT_MS; 999 } 1000 } 1001 clearProfilerIfNeeded()1002 void clearProfilerIfNeeded() { 1003 if (mListener == null) return; 1004 // Posting on handler so WM lock isn't held when we call into AM. 1005 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1006 WindowProcessListener::clearProfilerIfNeeded, mListener)); 1007 } 1008 updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, boolean updateOomAdj, boolean addPendingTopUid)1009 void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange, 1010 boolean updateOomAdj, boolean addPendingTopUid) { 1011 if (mListener == null) return; 1012 if (addPendingTopUid) { 1013 mAtm.mAmInternal.addPendingTopUid(mUid, mPid); 1014 } 1015 // Posting on handler so WM lock isn't held when we call into AM. 1016 final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo, 1017 mListener, updateServiceConnectionActivities, activityChange, updateOomAdj); 1018 mAtm.mH.sendMessage(m); 1019 } 1020 updateServiceConnectionActivities()1021 void updateServiceConnectionActivities() { 1022 if (mListener == null) return; 1023 // Posting on handler so WM lock isn't held when we call into AM. 1024 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1025 WindowProcessListener::updateServiceConnectionActivities, mListener)); 1026 } 1027 setPendingUiCleanAndForceProcessStateUpTo(int newState)1028 void setPendingUiCleanAndForceProcessStateUpTo(int newState) { 1029 if (mListener == null) return; 1030 // Posting on handler so WM lock isn't held when we call into AM. 1031 final Message m = PooledLambda.obtainMessage( 1032 WindowProcessListener::setPendingUiCleanAndForceProcessStateUpTo, 1033 mListener, newState); 1034 mAtm.mH.sendMessage(m); 1035 } 1036 isRemoved()1037 boolean isRemoved() { 1038 return mListener == null ? false : mListener.isRemoved(); 1039 } 1040 shouldSetProfileProc()1041 private boolean shouldSetProfileProc() { 1042 return mAtm.mProfileApp != null && mAtm.mProfileApp.equals(mName) 1043 && (mAtm.mProfileProc == null || mAtm.mProfileProc == this); 1044 } 1045 createProfilerInfoIfNeeded()1046 ProfilerInfo createProfilerInfoIfNeeded() { 1047 final ProfilerInfo currentProfilerInfo = mAtm.mProfilerInfo; 1048 if (currentProfilerInfo == null || currentProfilerInfo.profileFile == null 1049 || !shouldSetProfileProc()) { 1050 return null; 1051 } 1052 if (currentProfilerInfo.profileFd != null) { 1053 try { 1054 currentProfilerInfo.profileFd = currentProfilerInfo.profileFd.dup(); 1055 } catch (IOException e) { 1056 currentProfilerInfo.closeFd(); 1057 } 1058 } 1059 return new ProfilerInfo(currentProfilerInfo); 1060 } 1061 onStartActivity(int topProcessState, ActivityInfo info)1062 void onStartActivity(int topProcessState, ActivityInfo info) { 1063 if (mListener == null) return; 1064 String packageName = null; 1065 if ((info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0 1066 || !"android".equals(info.packageName)) { 1067 // Don't add this if it is a platform component that is marked to run in multiple 1068 // processes, because this is actually part of the framework so doesn't make sense 1069 // to track as a separate apk in the process. 1070 packageName = info.packageName; 1071 } 1072 // update ActivityManagerService.PendingStartActivityUids list. 1073 if (topProcessState == ActivityManager.PROCESS_STATE_TOP) { 1074 mAtm.mAmInternal.addPendingTopUid(mUid, mPid); 1075 } 1076 // Posting the message at the front of queue so WM lock isn't held when we call into AM, 1077 // and the process state of starting activity can be updated quicker which will give it a 1078 // higher scheduling group. 1079 final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity, 1080 mListener, topProcessState, shouldSetProfileProc(), packageName, 1081 info.applicationInfo.longVersionCode); 1082 mAtm.mH.sendMessageAtFrontOfQueue(m); 1083 } 1084 appDied(String reason)1085 void appDied(String reason) { 1086 if (mListener == null) return; 1087 // Posting on handler so WM lock isn't held when we call into AM. 1088 final Message m = PooledLambda.obtainMessage( 1089 WindowProcessListener::appDied, mListener, reason); 1090 mAtm.mH.sendMessage(m); 1091 } 1092 registerDisplayConfigurationListener(DisplayContent displayContent)1093 void registerDisplayConfigurationListener(DisplayContent displayContent) { 1094 if (displayContent == null) { 1095 return; 1096 } 1097 // A process can only register to one display to listen to the override configuration 1098 // change. Unregister existing listener if it has one before register the new one. 1099 unregisterDisplayConfigurationListener(); 1100 unregisterActivityConfigurationListener(); 1101 mDisplayId = displayContent.mDisplayId; 1102 displayContent.registerConfigurationChangeListener(this); 1103 } 1104 1105 @VisibleForTesting unregisterDisplayConfigurationListener()1106 void unregisterDisplayConfigurationListener() { 1107 if (mDisplayId == INVALID_DISPLAY) { 1108 return; 1109 } 1110 final DisplayContent displayContent = 1111 mAtm.mRootWindowContainer.getDisplayContent(mDisplayId); 1112 if (displayContent != null) { 1113 displayContent.unregisterConfigurationChangeListener(this); 1114 } 1115 mDisplayId = INVALID_DISPLAY; 1116 onMergedOverrideConfigurationChanged(Configuration.EMPTY); 1117 } 1118 registerActivityConfigurationListener(ActivityRecord activityRecord)1119 private void registerActivityConfigurationListener(ActivityRecord activityRecord) { 1120 if (activityRecord == null || activityRecord.containsListener(this)) { 1121 return; 1122 } 1123 // A process can only register to one activityRecord to listen to the override configuration 1124 // change. Unregister existing listener if it has one before register the new one. 1125 unregisterDisplayConfigurationListener(); 1126 unregisterActivityConfigurationListener(); 1127 mConfigActivityRecord = activityRecord; 1128 activityRecord.registerConfigurationChangeListener(this); 1129 } 1130 unregisterActivityConfigurationListener()1131 private void unregisterActivityConfigurationListener() { 1132 if (mConfigActivityRecord == null) { 1133 return; 1134 } 1135 mConfigActivityRecord.unregisterConfigurationChangeListener(this); 1136 mConfigActivityRecord = null; 1137 onMergedOverrideConfigurationChanged(Configuration.EMPTY); 1138 } 1139 1140 /** 1141 * Check if activity configuration override for the activity process needs an update and perform 1142 * if needed. By default we try to override the process configuration to match the top activity 1143 * config to increase app compatibility with multi-window and multi-display. The process will 1144 * always track the configuration of the non-finishing activity last added to the process. 1145 */ updateActivityConfigurationListener()1146 private void updateActivityConfigurationListener() { 1147 if (!mIsActivityConfigOverrideAllowed) { 1148 return; 1149 } 1150 1151 for (int i = mActivities.size() - 1; i >= 0; i--) { 1152 final ActivityRecord activityRecord = mActivities.get(i); 1153 if (!activityRecord.finishing) { 1154 // Eligible activity is found, update listener. 1155 registerActivityConfigurationListener(activityRecord); 1156 return; 1157 } 1158 } 1159 1160 // No eligible activities found, let's remove the configuration listener. 1161 unregisterActivityConfigurationListener(); 1162 } 1163 1164 @Override onConfigurationChanged(Configuration newGlobalConfig)1165 public void onConfigurationChanged(Configuration newGlobalConfig) { 1166 super.onConfigurationChanged(newGlobalConfig); 1167 updateConfiguration(); 1168 } 1169 1170 @Override onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig)1171 public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) { 1172 // Make sure that we don't accidentally override the activity type. 1173 mNewOverrideConfig.setTo(mergedOverrideConfig); 1174 mNewOverrideConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); 1175 super.onRequestedOverrideConfigurationChanged(mNewOverrideConfig); 1176 } 1177 updateConfiguration()1178 private void updateConfiguration() { 1179 final Configuration config = getConfiguration(); 1180 if (mLastReportedConfiguration.diff(config) == 0) { 1181 // Nothing changed. 1182 if (Build.IS_DEBUGGABLE && mHasImeService) { 1183 // TODO (b/135719017): Temporary log for debugging IME service. 1184 Slog.w(TAG_CONFIGURATION, "Current config: " + config 1185 + " unchanged for IME proc " + mName); 1186 } 1187 return; 1188 } 1189 1190 if (mListener.isCached()) { 1191 // This process is in a cached state. We will delay delivering the config change to the 1192 // process until the process is no longer cached. 1193 if (mPendingConfiguration == null) { 1194 mPendingConfiguration = new Configuration(config); 1195 } else { 1196 mPendingConfiguration.setTo(config); 1197 } 1198 return; 1199 } 1200 1201 dispatchConfigurationChange(config); 1202 } 1203 dispatchConfigurationChange(Configuration config)1204 private void dispatchConfigurationChange(Configuration config) { 1205 if (mThread == null) { 1206 if (Build.IS_DEBUGGABLE && mHasImeService) { 1207 // TODO (b/135719017): Temporary log for debugging IME service. 1208 Slog.w(TAG_CONFIGURATION, "Unable to send config for IME proc " + mName 1209 + ": no app thread"); 1210 } 1211 return; 1212 } 1213 if (DEBUG_CONFIGURATION) { 1214 Slog.v(TAG_CONFIGURATION, "Sending to proc " + mName + " new config " + config); 1215 } 1216 if (Build.IS_DEBUGGABLE && mHasImeService) { 1217 // TODO (b/135719017): Temporary log for debugging IME service. 1218 Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config); 1219 } 1220 1221 try { 1222 config.seq = mAtm.increaseConfigurationSeqLocked(); 1223 mAtm.getLifecycleManager().scheduleTransaction(mThread, 1224 ConfigurationChangeItem.obtain(config)); 1225 setLastReportedConfiguration(config); 1226 } catch (Exception e) { 1227 Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change", e); 1228 } 1229 } 1230 setLastReportedConfiguration(Configuration config)1231 private void setLastReportedConfiguration(Configuration config) { 1232 mLastReportedConfiguration.setTo(config); 1233 } 1234 getLastReportedConfiguration()1235 Configuration getLastReportedConfiguration() { 1236 return mLastReportedConfiguration; 1237 } 1238 1239 /** Returns the total time (in milliseconds) spent executing in both user and system code. */ getCpuTime()1240 public long getCpuTime() { 1241 return (mListener != null) ? mListener.getCpuTime() : 0; 1242 } 1243 addRecentTask(Task task)1244 void addRecentTask(Task task) { 1245 mRecentTasks.add(task); 1246 } 1247 removeRecentTask(Task task)1248 void removeRecentTask(Task task) { 1249 mRecentTasks.remove(task); 1250 } 1251 1252 @HotPath(caller = HotPath.OOM_ADJUSTMENT) hasRecentTasks()1253 public boolean hasRecentTasks() { 1254 synchronized (mAtm.mGlobalLockWithoutBoost) { 1255 return !mRecentTasks.isEmpty(); 1256 } 1257 } 1258 clearRecentTasks()1259 void clearRecentTasks() { 1260 for (int i = mRecentTasks.size() - 1; i >= 0; i--) { 1261 mRecentTasks.get(i).clearRootProcess(); 1262 } 1263 mRecentTasks.clear(); 1264 } 1265 appEarlyNotResponding(String annotation, Runnable killAppCallback)1266 public void appEarlyNotResponding(String annotation, Runnable killAppCallback) { 1267 Runnable targetRunnable = null; 1268 synchronized (mAtm.mGlobalLock) { 1269 if (mAtm.mController == null) { 1270 return; 1271 } 1272 1273 try { 1274 // 0 == continue, -1 = kill process immediately 1275 int res = mAtm.mController.appEarlyNotResponding(mName, mPid, annotation); 1276 if (res < 0 && mPid != MY_PID) { 1277 targetRunnable = killAppCallback; 1278 } 1279 } catch (RemoteException e) { 1280 mAtm.mController = null; 1281 Watchdog.getInstance().setActivityController(null); 1282 } 1283 } 1284 if (targetRunnable != null) { 1285 targetRunnable.run(); 1286 } 1287 } 1288 appNotResponding(String info, Runnable killAppCallback, Runnable serviceTimeoutCallback)1289 public boolean appNotResponding(String info, Runnable killAppCallback, 1290 Runnable serviceTimeoutCallback) { 1291 Runnable targetRunnable = null; 1292 synchronized (mAtm.mGlobalLock) { 1293 if (mAtm.mController == null) { 1294 return false; 1295 } 1296 1297 try { 1298 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately 1299 int res = mAtm.mController.appNotResponding(mName, mPid, info); 1300 if (res != 0) { 1301 if (res < 0 && mPid != MY_PID) { 1302 targetRunnable = killAppCallback; 1303 } else { 1304 targetRunnable = serviceTimeoutCallback; 1305 } 1306 } 1307 } catch (RemoteException e) { 1308 mAtm.mController = null; 1309 Watchdog.getInstance().setActivityController(null); 1310 return false; 1311 } 1312 } 1313 if (targetRunnable != null) { 1314 // Execute runnable outside WM lock since the runnable will hold AM lock 1315 targetRunnable.run(); 1316 return true; 1317 } 1318 return false; 1319 } 1320 1321 /** 1322 * Called to notify WindowProcessController of a change in the process's cached state. 1323 * 1324 * @param isCached whether or not the process is cached. 1325 */ 1326 @HotPath(caller = HotPath.OOM_ADJUSTMENT) onProcCachedStateChanged(boolean isCached)1327 public void onProcCachedStateChanged(boolean isCached) { 1328 if (!isCached) { 1329 synchronized (mAtm.mGlobalLockWithoutBoost) { 1330 if (mPendingConfiguration != null) { 1331 final Configuration config = mPendingConfiguration; 1332 mPendingConfiguration = null; 1333 dispatchConfigurationChange(config); 1334 } 1335 } 1336 } 1337 } 1338 1339 /** 1340 * Called to notify {@link WindowProcessController} of a started service. 1341 * 1342 * @param serviceInfo information describing the started service. 1343 */ onServiceStarted(ServiceInfo serviceInfo)1344 public void onServiceStarted(ServiceInfo serviceInfo) { 1345 String permission = serviceInfo.permission; 1346 if (permission == null) { 1347 return; 1348 } 1349 1350 // TODO: Audit remaining services for disabling activity override (Wallpaper, Dream, etc). 1351 switch (permission) { 1352 case Manifest.permission.BIND_INPUT_METHOD: 1353 mHasImeService = true; 1354 // Fall-through 1355 case Manifest.permission.BIND_ACCESSIBILITY_SERVICE: 1356 case Manifest.permission.BIND_VOICE_INTERACTION: 1357 // We want to avoid overriding the config of these services with that of the 1358 // activity as it could lead to incorrect display metrics. For ex, IME services 1359 // expect their config to match the config of the display with the IME window 1360 // showing. 1361 mIsActivityConfigOverrideAllowed = false; 1362 break; 1363 default: 1364 break; 1365 } 1366 } 1367 1368 @HotPath(caller = HotPath.OOM_ADJUSTMENT) onTopProcChanged()1369 public void onTopProcChanged() { 1370 synchronized (mAtm.mGlobalLockWithoutBoost) { 1371 mAtm.mVrController.onTopProcChangedLocked(this); 1372 } 1373 } 1374 1375 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isHomeProcess()1376 public boolean isHomeProcess() { 1377 synchronized (mAtm.mGlobalLockWithoutBoost) { 1378 return this == mAtm.mHomeProcess; 1379 } 1380 } 1381 1382 @HotPath(caller = HotPath.OOM_ADJUSTMENT) isPreviousProcess()1383 public boolean isPreviousProcess() { 1384 synchronized (mAtm.mGlobalLockWithoutBoost) { 1385 return this == mAtm.mPreviousProcess; 1386 } 1387 } 1388 setRunningRecentsAnimation(boolean running)1389 void setRunningRecentsAnimation(boolean running) { 1390 if (mRunningRecentsAnimation == running) { 1391 return; 1392 } 1393 mRunningRecentsAnimation = running; 1394 updateRunningRemoteOrRecentsAnimation(); 1395 } 1396 setRunningRemoteAnimation(boolean running)1397 void setRunningRemoteAnimation(boolean running) { 1398 if (mRunningRemoteAnimation == running) { 1399 return; 1400 } 1401 mRunningRemoteAnimation = running; 1402 updateRunningRemoteOrRecentsAnimation(); 1403 } 1404 updateRunningRemoteOrRecentsAnimation()1405 private void updateRunningRemoteOrRecentsAnimation() { 1406 1407 // Posting on handler so WM lock isn't held when we call into AM. 1408 mAtm.mH.sendMessage(PooledLambda.obtainMessage( 1409 WindowProcessListener::setRunningRemoteAnimation, mListener, 1410 mRunningRecentsAnimation || mRunningRemoteAnimation)); 1411 } 1412 1413 @Override toString()1414 public String toString() { 1415 return mOwner != null ? mOwner.toString() : null; 1416 } 1417 dump(PrintWriter pw, String prefix)1418 public void dump(PrintWriter pw, String prefix) { 1419 synchronized (mAtm.mGlobalLock) { 1420 if (mActivities.size() > 0) { 1421 pw.print(prefix); pw.println("Activities:"); 1422 for (int i = 0; i < mActivities.size(); i++) { 1423 pw.print(prefix); pw.print(" - "); pw.println(mActivities.get(i)); 1424 } 1425 } 1426 1427 if (mRecentTasks.size() > 0) { 1428 pw.println(prefix + "Recent Tasks:"); 1429 for (int i = 0; i < mRecentTasks.size(); i++) { 1430 pw.println(prefix + " - " + mRecentTasks.get(i)); 1431 } 1432 } 1433 1434 if (mVrThreadTid != 0) { 1435 pw.print(prefix); pw.print("mVrThreadTid="); pw.println(mVrThreadTid); 1436 } 1437 } 1438 pw.println(prefix + " Configuration=" + getConfiguration()); 1439 pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration()); 1440 pw.println(prefix + " mLastReportedConfiguration=" + mLastReportedConfiguration); 1441 } 1442 dumpDebug(ProtoOutputStream proto, long fieldId)1443 void dumpDebug(ProtoOutputStream proto, long fieldId) { 1444 if (mListener != null) { 1445 mListener.dumpDebug(proto, fieldId); 1446 } 1447 } 1448 } 1449