diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 8ad11d161cdca..7c5936720feb4 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1864,6 +1864,7 @@ public final class OomAdjuster { } int capabilityFromFGS = 0; // capability from foreground service. + boolean scheduleLikeTopApp = false; for (int is = psr.numberOfRunningServices() - 1; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND @@ -1975,6 +1976,8 @@ public final class OomAdjuster { int clientAdj = cstate.getCurRawAdj(); int clientProcState = cstate.getCurRawProcState(); + final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP; + // pass client's mAllowStartFgs to the app if client is not persistent process. if (cstate.getAllowedStartFgs() != REASON_DENIED && cstate.getMaxAdj() >= ProcessList.FOREGROUND_APP_ADJ) { @@ -2170,8 +2173,10 @@ public final class OomAdjuster { } if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP - && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) { + && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0 + && clientIsSystem) { schedGroup = ProcessList.SCHED_GROUP_TOP_APP; + scheduleLikeTopApp = true; } if (!trackedProcState) { @@ -2438,7 +2443,8 @@ public final class OomAdjuster { // Put bound foreground services in a special sched group for additional // restrictions on screen off if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE - && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE) { + && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE + && !scheduleLikeTopApp) { if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) { schedGroup = ProcessList.SCHED_GROUP_RESTRICTED; } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index 1c45203bb3c98..3404aff976d0a 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -1359,6 +1359,52 @@ public class MockingOomAdjusterTests { SCHED_GROUP_DEFAULT); } + @SuppressWarnings("GuardedBy") + @Test + public void testUpdateOomAdj_DoOne_ScheduleLikeTop() { + final ProcessRecord app1 = 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 client1 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID, + MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false)); + final ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID, + MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false)); + bindService(app1, client1, null, Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, + mock(IBinder.class)); + bindService(app2, client2, null, Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, + mock(IBinder.class)); + client1.mState.setMaxAdj(PERSISTENT_PROC_ADJ); + client2.mServices.setHasForegroundServices(true, 0); + + sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); + sService.mOomAdjuster.updateOomAdjLocked(app1, false, OomAdjuster.OOM_ADJ_REASON_NONE); + sService.mOomAdjuster.updateOomAdjLocked(app2, false, OomAdjuster.OOM_ADJ_REASON_NONE); + + assertProcStates(app1, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ, + SCHED_GROUP_DEFAULT); + assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, + SCHED_GROUP_DEFAULT); + + bindService(app1, client1, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); + bindService(app2, client2, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); + sService.mOomAdjuster.updateOomAdjLocked(app1, false, OomAdjuster.OOM_ADJ_REASON_NONE); + sService.mOomAdjuster.updateOomAdjLocked(app2, false, OomAdjuster.OOM_ADJ_REASON_NONE); + + assertProcStates(app1, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ, + SCHED_GROUP_TOP_APP); + assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, + SCHED_GROUP_DEFAULT); + + sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_ASLEEP); + sService.mOomAdjuster.updateOomAdjLocked(app1, false, OomAdjuster.OOM_ADJ_REASON_NONE); + sService.mOomAdjuster.updateOomAdjLocked(app2, false, OomAdjuster.OOM_ADJ_REASON_NONE); + assertProcStates(app1, PROCESS_STATE_IMPORTANT_FOREGROUND, VISIBLE_APP_ADJ, + SCHED_GROUP_TOP_APP); + assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, + SCHED_GROUP_DEFAULT); + } + @SuppressWarnings("GuardedBy") @Test public void testUpdateOomAdj_UidIdle_StopService() {