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

Commit e3289ae1 authored by Michael Wachenschwanz's avatar Michael Wachenschwanz
Browse files

Raise the threshold OomAdjuster will drop a service with UI to cached

When a client binds to a proc that has shown UI, OomAdjuster will
aggressively try to drop the service to the cached state to try to
recover memory from the UI process faster. The threshold is based on the
client oom score, but the current threshold is too agressive at
PERCEPTIBLE_APP_ADJ. Raise the threshold to SERVICE_ADJ, the highest
score that can reasonably be performing timely work.

Flag: com.android.server.am.raise_bound_ui_service_threshold
Fixes: 391691057
Test: atest MockingOomAdjuster
Change-Id: Ia17ad5798ef254c9cc1527d85838b833053faf1f
parent eb96c368
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -441,6 +441,12 @@ public class OomAdjuster {
    @GuardedBy("mService")
    private long mNextFollowUpUpdateUptimeMs = NO_FOLLOW_UP_TIME;

    /**
     * The oom score a client needs to be to raise a service with UI out of cache.
     */
    private static final int CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD =
            Flags.raiseBoundUiServiceThreshold() ? SERVICE_ADJ : PERCEPTIBLE_APP_ADJ;

    @VisibleForTesting
    public static class Injector {
        boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -2879,15 +2885,12 @@ public class OomAdjuster {
                }
            }
            if (adj > clientAdj) {
                // If this process has recently shown UI, and
                // the process that is binding to it is less
                // important than being visible, then we don't
                // care about the binding as much as we care
                // about letting this process get into the LRU
                // list to be killed and restarted if needed for
                // memory.
                // If this process has recently shown UI, and the process that is binding to it
                // is less important than a state that can be actively running, then we don't
                // care about the binding as much as we care about letting this process get into
                // the LRU list to be killed and restarted if needed for memory.
                if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                        && clientAdj > PERCEPTIBLE_APP_ADJ) {
                        && clientAdj > CACHING_UI_SERVICE_CLIENT_ADJ_THRESHOLD) {
                    if (adj >= CACHED_APP_MIN_ADJ) {
                        adjType = "cch-bound-ui-services";
                    }
+11 −0
Original line number Diff line number Diff line
@@ -298,3 +298,14 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "raise_bound_ui_service_threshold"
    namespace: "backstage_power"
    is_fixed_read_only: true
    description: "Raise the threshold OomAdjuster will drop a service with UI to cached."
    bug: "391691057"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+45 −0
Original line number Diff line number Diff line
@@ -3359,6 +3359,51 @@ public class MockingOomAdjusterTests {
        }
    }

    @SuppressWarnings("GuardedBy")
    @Test
    public void testUpdateOomAdj_DoAll_BindUiServiceFromClientService() {
        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
        ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
        ServiceRecord s = makeServiceRecord(client);
        mProcessStateController.setStartRequested(s, true);
        mProcessStateController.setServiceLastActivityTime(s, SystemClock.uptimeMillis());
        bindService(app, client, null, null, 0, mock(IBinder.class));

        setWakefulness(PowerManagerInternal.WAKEFULNESS_AWAKE);
        updateOomAdj(app, client);
        if (Flags.raiseBoundUiServiceThreshold()) {
            assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
                    "service");
        } else {
            final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
                    ? sFirstUiCachedAdj : sFirstCachedAdj;
            assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND,
                    "cch-bound-ui-services");
        }
    }

    @SuppressWarnings("GuardedBy")
    @Test
    public void testUpdateOomAdj_DoAll_BindUiServiceFromClientHome() {
        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
        ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));

        WindowProcessController wpc = client.getWindowProcessController();
        doReturn(true).when(wpc).isHomeProcess();
        bindService(app, client, null, null, 0, mock(IBinder.class));
        setWakefulness(PowerManagerInternal.WAKEFULNESS_AWAKE);
        updateOomAdj(app, client);

        final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
                ? sFirstUiCachedAdj : sFirstCachedAdj;
        assertProcStates(app, PROCESS_STATE_HOME, expectedAdj, SCHED_GROUP_BACKGROUND,
                "cch-bound-ui-services");
    }

    private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
            String packageName, boolean hasShownUi) {
        return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi(