diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 0591704a05021..12f46569bd20c 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -376,7 +376,11 @@ public final class OomAdjuster { ConnectionRecord cr = pr.connections.valueAt(i); ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0 ? cr.binding.service.isolatedProc : cr.binding.service.app; - if (service == null || service == pr || (containsCycle |= service.mReachable)) { + if (service == null || service == pr) { + continue; + } + containsCycle |= service.mReachable; + if (service.mReachable) { continue; } if ((cr.flags & (Context.BIND_WAIVE_PRIORITY @@ -394,6 +398,10 @@ public final class OomAdjuster { if (provider == null || provider == pr || (containsCycle |= provider.mReachable)) { continue; } + containsCycle |= provider.mReachable; + if (provider.mReachable) { + continue; + } queue.offer(provider); provider.mReachable = true; } @@ -482,12 +490,15 @@ public final class OomAdjuster { // need to reset cycle state before calling computeOomAdjLocked because of service conns for (int i = numProc - 1; i >= 0; i--) { ProcessRecord app = activeProcesses.get(i); - app.containsCycle = false; app.mReachable = false; - app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY); - app.setCurRawAdj(ProcessList.UNKNOWN_ADJ); - app.setCapability = PROCESS_CAPABILITY_NONE; - app.resetCachedInfo(); + // No need to compute again it has been evaluated in previous iteration + if (app.adjSeq != mAdjSeq) { + app.containsCycle = false; + app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY); + app.setCurRawAdj(ProcessList.UNKNOWN_ADJ); + app.setCapability = PROCESS_CAPABILITY_NONE; + app.resetCachedInfo(); + } } for (int i = numProc - 1; i >= 0; i--) { ProcessRecord app = activeProcesses.get(i); 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 6c09239251bd9..8e6114aaeffeb 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -1051,6 +1051,35 @@ public class MockingOomAdjusterTests { assertEquals(PROCESS_STATE_CACHED_EMPTY, app.setProcState); } + @SuppressWarnings("GuardedBy") + @Test + public void testUpdateOomAdj_DoOne_Service_Chain_BoundByFgService_Cycle_2() { + ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, + MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false)); + ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, + MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false)); + bindService(app, client, null, 0, mock(IBinder.class)); + bindService(client, app, null, 0, mock(IBinder.class)); + ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID, + MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false)); + bindService(client2, client, null, 0, mock(IBinder.class)); + client.setHasForegroundServices(true, 0); + ArrayList lru = sService.mProcessList.mLruProcesses; + lru.clear(); + lru.add(app); + lru.add(client); + lru.add(client2); + sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE; + sService.mOomAdjuster.updateOomAdjLocked(app, true, OomAdjuster.OOM_ADJ_REASON_NONE); + + assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, + SCHED_GROUP_DEFAULT); + assertProcStates(client, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, + SCHED_GROUP_DEFAULT); + assertProcStates(client2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, + SCHED_GROUP_DEFAULT); + } + @SuppressWarnings("GuardedBy") @Test public void testUpdateOomAdj_DoOne_Service_Chain_BoundByFgService_Cycle_Branch() {