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

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

Migrate tempAllowList and appDied full oomAdj updates to partial updates

Temp allowlisting just needs to run an update on all process of the uid
being updated (and their clients). When an process dies, a partial
update needs to be done on all of processes bound by the dying process.

Flag: com.android.server.am.migrate_full_oomadj_updates
Bug: 324915545
Test: atest MockingOomAdjusterTests
Test: atest ActivityManagerProcessStateTest
Change-Id: I203c23be38490811e00566cb239bfe423cb90ba2
parent e2577bc6
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -3541,14 +3541,24 @@ public class ActivityManagerService extends IActivityManager.Stub
                mAppProfiler.setAllowLowerMemLevelLocked(false);
                doLowMem = false;
            }
            if (doOomAdj) {
                if (Flags.migrateFullOomadjUpdates()) {
                    app.forEachConnectionHost((host) -> enqueueOomAdjTargetLocked(host));
                }
            }
            EventLogTags.writeAmProcDied(app.userId, pid, app.processName, setAdj, setProcState);
            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
            handleAppDiedLocked(app, pid, false, true, fromBinderDied);
            if (doOomAdj) {
                if (Flags.migrateFullOomadjUpdates()) {
                    updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_PROCESS_END);
                } else {
                    updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END);
                }
            }
            if (doLowMem) {
                mAppProfiler.doLowMemReportIfNeededLocked(app);
            }
@@ -17722,11 +17732,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    @GuardedBy({"this", "mProcLock"})
    final void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
        mOomAdjuster.setAppIdTempAllowlistStateLSP(uid, onAllowlist);
    }
    @GuardedBy({"this", "mProcLock"})
    final void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
        mOomAdjuster.setUidTempAllowlistStateLSP(uid, onAllowlist);
@@ -18689,7 +18694,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    } else {
                        mFgsStartTempAllowList.removeUid(changingUid);
                    }
                    setAppIdTempAllowlistStateLSP(changingUid, adding);
                    setUidTempAllowlistStateLSP(changingUid, adding);
                }
            }
        }
+8 −17
Original line number Diff line number Diff line
@@ -3695,30 +3695,21 @@ public class OomAdjuster {
        }
    }

    @GuardedBy({"mService", "mProcLock"})
    void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
        boolean changed = false;
        for (int i = mActiveUids.size() - 1; i >= 0; i--) {
            final UidRecord uidRec = mActiveUids.valueAt(i);
            if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) {
                uidRec.setCurAllowListed(onAllowlist);
                changed = true;
            }
        }
        if (changed) {
            updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
        }
    }

    @GuardedBy({"mService", "mProcLock"})
    void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
        boolean changed = false;
        final UidRecord uidRec = mActiveUids.get(uid);
        if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) {
            uidRec.setCurAllowListed(onAllowlist);
            if (Flags.migrateFullOomadjUpdates()) {
                for (int i = uidRec.getNumOfProcs() - 1; i >= 0; i--) {
                    enqueueOomAdjTargetLocked(uidRec.getProcessRecordByIndex(i));
                }
                updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_ALLOWLIST);
            } else {
                updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
            }
        }
    }

    @GuardedBy("mService")
    void dumpProcessListVariablesLocked(ProtoOutputStream proto) {
+19 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ import com.android.server.wm.WindowProcessListener;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

/**
 * Full information about a particular process that
@@ -1692,4 +1693,22 @@ class ProcessRecord implements WindowProcessListener {
                && !mOptRecord.shouldNotFreeze()
                && mState.getCurAdj() >= ProcessList.FREEZER_CUTOFF_ADJ;
    }

    public void forEachConnectionHost(Consumer<ProcessRecord> consumer) {
        for (int i = mServices.numberOfConnections() - 1; i >= 0; i--) {
            final ConnectionRecord cr = mServices.getConnectionAt(i);
            final ProcessRecord service = cr.binding.service.app;
            consumer.accept(service);
        }
        for (int i = mServices.numberOfSdkSandboxConnections() - 1; i >= 0; i--) {
            final ConnectionRecord cr = mServices.getSdkSandboxConnectionAt(i);
            final ProcessRecord service = cr.binding.service.app;
            consumer.accept(service);
        }
        for (int i = mProviders.numberOfProviderConnections() - 1; i >= 0; i--) {
            ContentProviderConnection cpc = mProviders.getProviderConnectionAt(i);
            ProcessRecord provider = cpc.provider.proc;
            consumer.accept(provider);
        }
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -106,3 +106,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "migrate_full_oomadj_updates"
    namespace: "backstage_power"
    description: "Migrate full updates to partial updates where possible"
    bug: "324915545"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+73 −0
Original line number Diff line number Diff line
@@ -245,9 +245,11 @@ public class MockingOomAdjusterTests {
        LocalServices.removeServiceForTest(PackageManagerInternal.class);
    }

    @SuppressWarnings("GuardedBy")
    @After
    public void tearDown() {
        sService.mOomAdjuster.resetInternal();
        sService.mOomAdjuster.mActiveUids.clear();
    }

    private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
@@ -2816,6 +2818,69 @@ public class MockingOomAdjusterTests {
                SCHED_GROUP_DEFAULT);
    }

    @SuppressWarnings("GuardedBy")
    @Test
    public void testSetUidTempAllowlistState() {
        final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
        final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
        setProcessesToLru(app, app2);

        // App1 binds to app2 and gets temp allowlisted.
        bindService(app2, app, null, null, 0, mock(IBinder.class));
        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, true);

        assertEquals(true, app.getUidRecord().isSetAllowListed());
        assertEquals(true, app.mOptRecord.shouldNotFreeze());
        assertEquals(true, app2.mOptRecord.shouldNotFreeze());

        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
        assertEquals(false, app.getUidRecord().isSetAllowListed());
        assertEquals(false, app.mOptRecord.shouldNotFreeze());
        assertEquals(false, app2.mOptRecord.shouldNotFreeze());
    }

    @SuppressWarnings("GuardedBy")
    @Test
    public void testSetUidTempAllowlistState_multipleAllowlistClients() {
        final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
        final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
        final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
        setProcessesToLru(app, app2, app3);

        // App1 and app2 both bind to app3 and get temp allowlisted.
        bindService(app3, app, null, null, 0, mock(IBinder.class));
        bindService(app3, app2, null, null, 0, mock(IBinder.class));
        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, true);
        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP2_UID, true);

        assertEquals(true, app.getUidRecord().isSetAllowListed());
        assertEquals(true, app2.getUidRecord().isSetAllowListed());
        assertEquals(true, app.mOptRecord.shouldNotFreeze());
        assertEquals(true, app2.mOptRecord.shouldNotFreeze());
        assertEquals(true, app3.mOptRecord.shouldNotFreeze());

        // Remove app1 from allowlist.
        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
        assertEquals(false, app.getUidRecord().isSetAllowListed());
        assertEquals(true, app2.getUidRecord().isSetAllowListed());
        assertEquals(false, app.mOptRecord.shouldNotFreeze());
        assertEquals(true, app2.mOptRecord.shouldNotFreeze());
        assertEquals(true, app3.mOptRecord.shouldNotFreeze());

        // Now remove app2 from allowlist.
        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP2_UID, false);
        assertEquals(false, app.getUidRecord().isSetAllowListed());
        assertEquals(false, app2.getUidRecord().isSetAllowListed());
        assertEquals(false, app.mOptRecord.shouldNotFreeze());
        assertEquals(false, app2.mOptRecord.shouldNotFreeze());
        assertEquals(false, app3.mOptRecord.shouldNotFreeze());
    }

    private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
            String packageName, boolean hasShownUi) {
        return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi(
@@ -3057,6 +3122,14 @@ public class MockingOomAdjusterTests {
                receivers.addCurReceiver(mock(BroadcastRecord.class));
            }
            providers.setLastProviderTime(mLastProviderTime);

            UidRecord uidRec = sService.mOomAdjuster.mActiveUids.get(mUid);
            if (uidRec == null) {
                uidRec = new UidRecord(mUid, sService);
                sService.mOomAdjuster.mActiveUids.put(mUid, uidRec);
            }
            uidRec.addProcess(app);
            app.setUidRecord(uidRec);
            return app;
        }
    }