Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5a6c03f authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Use foreground sched group for process showing UI while dozing

After device enters dozing mode, SystemUI will be
BOUND_FOREGROUND_SERVICE + GROUP_RESTRICTED. Then jank could happen
when updating the UI, e.g. add/remove notification, update clock.

If AOD is not enabled, when the screen is turned on without awake,
the priority will boost to PERSISTENT_UI + TOP_APP for 2s, and then
before screen goes off, it will keep PERSISTENT + GROUP_DEFAULT.

If AOD is enabled, the priority will also keep at least
PERSISTENT + GROUP_DEFAULT.

Bug: 308601407
Bug: 261162899
Test: atest DisplayPolicyTests#testVisibleProcessWhileDozing
Test: Disable "Always show time and info" and turn off screen.
      Send a notification to turn on screen.
      > adb shell dumpsys activity oom | grep systemui
      It will show "T/ /PERU" in 2s, and then "F/ /PER" if screen
      is still on. After screen is off automatically by timeout,
      it will return to "R/ /BFGS".
Test: Enable "Always show time and info" and turn off screen.
      > adb shell dumpsys activity oom | grep systemui
      It will show "F/ /PER" instead of "R/ /BFGS"
Change-Id: Ic6867adc9814ea96b15074feea85b7ce1cffb9e3
parent 65959325
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1829,7 +1829,7 @@ public class OomAdjuster {
                    // screen on or animating, promote UI
                    state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
                    state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP);
                } else {
                } else if (!app.getWindowProcessController().isShowingUiWhileDozing()) {
                    // screen off, restrict UI scheduling
                    state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
                    state.setCurrentSchedulingGroup(SCHED_GROUP_RESTRICTED);
+2 −0
Original line number Diff line number Diff line
@@ -414,6 +414,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    boolean mHasCompanionDeviceSetupFeature;
    /** The process of the top most activity. */
    volatile WindowProcessController mTopApp;
    /** The process showing UI while the device is dozing. */
    volatile WindowProcessController mVisibleDozeUiProcess;
    /**
     * This is the process holding the activity the user last visited that is in a different process
     * from the one they are currently in.
+20 −0
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.PrintWriterPrinter;
@@ -781,6 +782,12 @@ public class DisplayPolicy {
            if (!mDisplayContent.isDefaultDisplay) {
                return;
            }
            if (awake) {
                mService.mAtmService.mVisibleDozeUiProcess = null;
            } else if (mScreenOnFully && mNotificationShade != null) {
                // Screen is still on, so it may be showing an always-on UI.
                mService.mAtmService.mVisibleDozeUiProcess = mNotificationShade.getProcess();
            }
            mService.mAtmService.mKeyguardController.updateDeferTransitionForAod(
                    mAwake /* waiting */);
        }
@@ -826,12 +833,24 @@ public class DisplayPolicy {
    }

    public void screenTurnedOn(ScreenOnListener screenOnListener) {
        WindowProcessController visibleDozeUiProcess = null;
        synchronized (mLock) {
            mScreenOnEarly = true;
            mScreenOnFully = false;
            mKeyguardDrawComplete = false;
            mWindowManagerDrawComplete = false;
            mScreenOnListener = screenOnListener;
            if (!mAwake && mNotificationShade != null) {
                // The screen is turned on without awake state. It is usually triggered by an
                // adding notification, so make the UI process have a higher priority.
                visibleDozeUiProcess = mNotificationShade.getProcess();
                mService.mAtmService.mVisibleDozeUiProcess = visibleDozeUiProcess;
            }
        }
        // The method calls AM directly, so invoke it outside the lock.
        if (visibleDozeUiProcess != null) {
            Trace.instant(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurnedOnWhileDozing");
            mService.mAtmService.setProcessAnimatingWhileDozing(visibleDozeUiProcess);
        }
    }

@@ -842,6 +861,7 @@ public class DisplayPolicy {
            mKeyguardDrawComplete = false;
            mWindowManagerDrawComplete = false;
            mScreenOnListener = null;
            mService.mAtmService.mVisibleDozeUiProcess = null;
        }
    }

+5 −0
Original line number Diff line number Diff line
@@ -1863,6 +1863,11 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        return this == mAtm.mHomeProcess;
    }

    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
    public boolean isShowingUiWhileDozing() {
        return this == mAtm.mVisibleDozeUiProcess;
    }

    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
    public boolean isPreviousProcess() {
        return this == mAtm.mPreviousProcess;
+20 −0
Original line number Diff line number Diff line
@@ -274,6 +274,26 @@ public class DisplayPolicyTests extends WindowTestsBase {
        assertEquals(mAppWindow, policy.getTopFullscreenOpaqueWindow());
    }

    @SetupWindows(addWindows = W_NOTIFICATION_SHADE)
    @Test
    public void testVisibleProcessWhileDozing() {
        final WindowProcessController wpc = mNotificationShadeWindow.getProcess();
        final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
        policy.addWindowLw(mNotificationShadeWindow, mNotificationShadeWindow.mAttrs);

        policy.screenTurnedOff();
        policy.setAwake(false);
        policy.screenTurnedOn(null /* screenOnListener */);
        assertTrue(wpc.isShowingUiWhileDozing());
        policy.screenTurnedOff();
        assertFalse(wpc.isShowingUiWhileDozing());

        policy.screenTurnedOn(null /* screenOnListener */);
        assertTrue(wpc.isShowingUiWhileDozing());
        policy.setAwake(true);
        assertFalse(wpc.isShowingUiWhileDozing());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testMainAppWindowDisallowFitSystemWindowTypes() {
        final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();