Demote top app scheduling group when unlocking

SystemUI may be running the unlock animation. If both SystemUI
and the resuming top app have top-app scheduling group, there
may be CPU contention which causes animation jank.

An exceptional case is unlocking to home which may also animate,
then keep original behavior: both system ui and home will have
top-app scheduling group.

Bug: 240356132
Bug: 226367352
Test: Launch calculator.
      Keep executing command "adb shell dumpsys activity o | grep calc"
      Lock and unlock device.
      The dump will have the changes:
      b/A/TPSL ----  t: 0 20687:calc/u0a158 (top-sleeping)
      F/A/TOP  LCMN  t: 0 20687:calc/u0a158 (intermediate-top-activity)
      T/A/TOP  LCMN  t: 0 20687:calc/u0a158 (top-activity)
      (b=BG, F=FG, T=TOP)

Change-Id: Id0fd2491a11bac7b81bc654e646b3d01643ca8b4
Merged-In: Id0fd2491a11bac7b81bc654e646b3d01643ca8b4
(cherry picked from commit f3139a9e51)
This commit is contained in:
Riddle Hsu
2022-05-17 16:24:19 -06:00
parent f3bbee232f
commit bea0e67d0d
3 changed files with 50 additions and 7 deletions

View File

@@ -1556,14 +1556,22 @@ public class OomAdjuster {
boolean foregroundActivities = false;
boolean hasVisibleActivities = false;
if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
if (app == topApp && (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP
|| PROCESS_STATE_CUR_TOP == PROCESS_STATE_IMPORTANT_FOREGROUND)) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
state.setAdjType("top-activity");
if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP) {
schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
state.setAdjType("top-activity");
} else {
// Demote the scheduling group to avoid CPU contention if there is another more
// important process which also uses top-app, such as if SystemUI is animating.
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
state.setAdjType("intermediate-top-activity");
}
foregroundActivities = true;
hasVisibleActivities = true;
procState = PROCESS_STATE_CUR_TOP;
procState = PROCESS_STATE_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
}

View File

@@ -64,8 +64,8 @@ import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
import static android.provider.Settings.System.FONT_SCALE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT;
import static android.view.WindowManager.TRANSIT_WAKE;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
@@ -400,6 +400,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
/** The time at which the previous process was last visible. */
private long mPreviousProcessVisibleTime;
/**
* It can be true from keyguard-going-away to set-keyguard-shown. And getTopProcessState() will
* return {@link ActivityManager#PROCESS_STATE_IMPORTANT_FOREGROUND} to avoid top app from
* preempting CPU while keyguard is animating.
*/
private volatile boolean mDemoteTopAppDuringUnlocking;
/** List of intents that were used to start the most recent tasks. */
private RecentTasks mRecentTasks;
/** State of external calls telling us if the device is awake or asleep. */
@@ -2830,12 +2837,24 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
keyguardShowing);
mH.sendMessage(msg);
}
// Always reset the state regardless of keyguard-showing change, because that means the
// unlock is either completed or canceled.
if (mDemoteTopAppDuringUnlocking) {
mDemoteTopAppDuringUnlocking = false;
// The scheduling group of top process was demoted by unlocking, so recompute
// to restore its real top priority if possible.
if (mTopApp != null) {
mTopApp.scheduleUpdateOomAdj();
}
}
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "setLockScreenShown");
mRootWindowContainer.forAllDisplays(displayContent -> {
mKeyguardController.setKeyguardShown(displayContent.getDisplayId(),
keyguardShowing, aodShowing);
});
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Binder.restoreCallingIdentity(ident);
}
}
@@ -2862,6 +2881,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// animation of system UI. Even if AOD is not enabled, it should be no harm.
final WindowProcessController proc;
synchronized (mGlobalLockWithoutBoost) {
mDemoteTopAppDuringUnlocking = false;
final WindowState notificationShade = mRootWindowContainer.getDefaultDisplay()
.getDisplayPolicy().getNotificationShade();
proc = notificationShade != null
@@ -3399,8 +3419,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
try {
synchronized (mGlobalLock) {
// Keyguard asked us to clear the home task snapshot before going away, so do that.
if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT) != 0) {
if ((flags & KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT) != 0) {
mActivityClientController.invalidateHomeTaskSnapshot(null /* token */);
} else if (mKeyguardShown) {
// Only set if it is not unlocking to launcher which may also animate.
mDemoteTopAppDuringUnlocking = true;
}
mRootWindowContainer.forAllDisplays(displayContent -> {
@@ -5595,12 +5618,17 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public int getTopProcessState() {
final int topState = mTopProcessState;
if (mDemoteTopAppDuringUnlocking && topState == ActivityManager.PROCESS_STATE_TOP) {
// The unlocking UI is more important, so defer the top state of app.
return ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
}
if (mRetainPowerModeAndTopProcessState) {
// There is a launching app while device may be sleeping, force the top state so
// the launching process can have top-app scheduling group.
return ActivityManager.PROCESS_STATE_TOP;
}
return mTopProcessState;
return topState;
}
@HotPath(caller = HotPath.PROCESS_CHANGE)

View File

@@ -1126,6 +1126,13 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mAtm.mH.sendMessage(m);
}
/** Refreshes oom adjustment and process state of this process. */
void scheduleUpdateOomAdj() {
mAtm.mH.sendMessage(PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo,
mListener, false /* updateServiceConnectionActivities */,
false /* activityChange */, true /* updateOomAdj */));
}
/** Makes the process have top state before oom-adj is computed from a posted message. */
void addToPendingTop() {
mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread);