Loading services/core/java/com/android/server/am/ActivityManagerService.java +12 −7 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -18689,7 +18694,7 @@ public class ActivityManagerService extends IActivityManager.Stub } else { mFgsStartTempAllowList.removeUid(changingUid); } setAppIdTempAllowlistStateLSP(changingUid, adding); setUidTempAllowlistStateLSP(changingUid, adding); } } } services/core/java/com/android/server/am/OomAdjuster.java +8 −17 Original line number Diff line number Diff line Loading @@ -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) { Loading services/core/java/com/android/server/am/ProcessRecord.java +19 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); } } } services/core/java/com/android/server/am/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -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 } } services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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( Loading Loading @@ -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; } } Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +12 −7 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -18689,7 +18694,7 @@ public class ActivityManagerService extends IActivityManager.Stub } else { mFgsStartTempAllowList.removeUid(changingUid); } setAppIdTempAllowlistStateLSP(changingUid, adding); setUidTempAllowlistStateLSP(changingUid, adding); } } }
services/core/java/com/android/server/am/OomAdjuster.java +8 −17 Original line number Diff line number Diff line Loading @@ -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) { Loading
services/core/java/com/android/server/am/ProcessRecord.java +19 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); } } }
services/core/java/com/android/server/am/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -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 } }
services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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( Loading Loading @@ -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; } } Loading