Loading services/core/java/com/android/server/am/OomAdjuster.java +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ALLOWLIST; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BACKUP; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SERVICE_BINDER_CALL; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BIND_SERVICE; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_COMPONENT_DISABLED; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_EXECUTING_SERVICE; Loading @@ -52,6 +51,7 @@ import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RECONFIGURATION import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SERVICE_BINDER_CALL; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHELL; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER; Loading services/core/java/com/android/server/am/OomAdjusterImpl.java +45 −19 Original line number Diff line number Diff line Loading @@ -991,13 +991,12 @@ public class OomAdjusterImpl extends OomAdjuster { ConnectionRecord cr = psr.getConnectionAt(i); ProcessRecord service = cr.hasFlag(ServiceInfo.FLAG_ISOLATED_PROCESS) ? cr.binding.service.isolationHostProc : cr.binding.service.app; if (service == null || service == app || (service.mState.getMaxAdj() >= SYSTEM_ADJ && service.mState.getMaxAdj() < FOREGROUND_APP_ADJ) || (service.mState.getCurAdj() <= FOREGROUND_APP_ADJ && service.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && service.mState.getCurProcState() <= PROCESS_STATE_TOP) || (service.isSdkSandbox && cr.binding.attributedClient != null)) { if (service == null || service == app || isSandboxAttributedConnection(cr, service)) { continue; } // If the host is high priority, skip the connection recompute unless the connection has // flags, which needs extra consideration. e.g. BIND_SCHEDULE_LIKE_TOP_APP if (isHighPriorityProcess(service) && allowSkipForBindScheduleLikeTopApp(cr, service)) { continue; } connectionConsumer.accept(cr, service); Loading @@ -1006,12 +1005,10 @@ public class OomAdjusterImpl extends OomAdjuster { for (int i = psr.numberOfSdkSandboxConnections() - 1; i >= 0; i--) { final ConnectionRecord cr = psr.getSdkSandboxConnectionAt(i); final ProcessRecord service = cr.binding.service.app; if (service == null || service == app || (service.mState.getMaxAdj() >= SYSTEM_ADJ && service.mState.getMaxAdj() < FOREGROUND_APP_ADJ) || (service.mState.getCurAdj() <= FOREGROUND_APP_ADJ && service.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && service.mState.getCurProcState() <= PROCESS_STATE_TOP)) { if (service == null || service == app) { continue; } if (isHighPriorityProcess(service) && allowSkipForBindScheduleLikeTopApp(cr, service)) { continue; } connectionConsumer.accept(cr, service); Loading @@ -1021,18 +1018,47 @@ public class OomAdjusterImpl extends OomAdjuster { for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) { ContentProviderConnection cpc = ppr.getProviderConnectionAt(i); ProcessRecord provider = cpc.provider.proc; if (provider == null || provider == app || (provider.mState.getMaxAdj() >= ProcessList.SYSTEM_ADJ && provider.mState.getMaxAdj() < FOREGROUND_APP_ADJ) || (provider.mState.getCurAdj() <= FOREGROUND_APP_ADJ && provider.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && provider.mState.getCurProcState() <= PROCESS_STATE_TOP)) { if (provider == null || provider == app || isHighPriorityProcess(provider)) { continue; } connectionConsumer.accept(cpc, provider); } } /** * This is one of the condition that blocks the skipping of connection evaluation. This method * returns false when the given connection has flag {@link Context#BIND_SCHEDULE_LIKE_TOP_APP} * but the host process has not set the corresponding flag, * {@link ProcessStateRecord#mScheduleLikeTopApp}. */ private static boolean allowSkipForBindScheduleLikeTopApp(ConnectionRecord cr, ProcessRecord host) { // If feature flag for optionally blocking skipping is disabled. Always allow skipping. if (!Flags.notSkipConnectionRecomputeForBindScheduleLikeTopApp()) { return true; } // Need to check shouldScheduleLikeTopApp otherwise, there will be too many recompute which // leads to OOM. return !(cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP) && !host.mState.shouldScheduleLikeTopApp()); } private static boolean isSandboxAttributedConnection(ConnectionRecord cr, ProcessRecord host) { return host.isSdkSandbox && cr.binding.attributedClient != null; } private static boolean isHighPriorityProcess(ProcessRecord proc) { final boolean isPersistentSystemProcess = proc.mState.getMaxAdj() >= SYSTEM_ADJ && proc.mState.getMaxAdj() < FOREGROUND_APP_ADJ; final boolean isEffectivelyForeground = proc.mState.getCurAdj() <= FOREGROUND_APP_ADJ && proc.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && proc.mState.getCurProcState() <= PROCESS_STATE_TOP; return isPersistentSystemProcess || isEffectivelyForeground; } /** * Stream the connections from clients with {@code app} as the host to {@code * connectionConsumer}. Loading services/core/java/com/android/server/am/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -258,3 +258,10 @@ flag { description: "Enable ActivityManagerStructured Service" bug: "419409018" } flag { name: "not_skip_connection_recompute_for_bind_schedule_like_top_app" namespace: "wear_frameworks" description: "If a connection has flag BIND_SCHEDULE_LIKE_TOP_APP but the host process has not set the corresponding flag, do not skip the connection recompute." bug: "417720000" } services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +86 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP; import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP_BOUND; import static com.android.server.am.ProcessList.SERVICE_ADJ; import static com.android.server.am.ProcessList.SERVICE_B_ADJ; import static com.android.server.am.ProcessList.SYSTEM_ADJ; import static com.android.server.am.ProcessList.UNKNOWN_ADJ; import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ; import static com.android.server.wm.WindowProcessController.ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED; Loading Loading @@ -115,6 +116,7 @@ import android.os.PowerManagerInternal; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; Loading Loading @@ -3760,6 +3762,90 @@ public class MockingOomAdjusterTests { SCHED_GROUP_RESTRICTED); } @SuppressWarnings("GuardedBy") @Test public void testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostGetsTopSchedGroup() { // When system client binds a service with BIND_SCHEDULE_LIKE_TOP_APP, the service should // will be prioritized as top app. ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); host.mState.setCurrentSchedulingGroup(SCHED_GROUP_DEFAULT); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, SYSTEM_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); assertTrue(host.mState.shouldScheduleLikeTopApp()); assertEquals(SCHED_GROUP_TOP_APP, host.mState.getCurrentSchedulingGroup()); } @SuppressWarnings("GuardedBy") @Test public void testUpdateOomAdj_bindScheduleLikeTopApp_nonSystemClient_hostNotGetTopSchedGroup() { ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); assertFalse(host.mState.shouldScheduleLikeTopApp()); assertNotEquals(SCHED_GROUP_TOP_APP, host.mState.getCurrentSchedulingGroup()); } @SuppressWarnings("GuardedBy") @Test @DisableFlags(Flags.FLAG_NOT_SKIP_CONNECTION_RECOMPUTE_FOR_BIND_SCHEDULE_LIKE_TOP_APP) public void testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostPrivileged_skipConnectionCompute_hostNotGetTopSchedGroup() { // Similar to testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostGetsTopSchedGroup, // but now the host process is already marked as privileged(see // OomAdjusterImpl#isHighPriorityProcess for detail). In this case, connection evaluation // will be skipped, as a result, the scheduling group stays default. ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); mProcessStateController.setMaxAdj(host, PERSISTENT_SERVICE_ADJ); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, SYSTEM_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); // The update for host by its client connection evaluation is skipped. assertFalse(host.mState.shouldScheduleLikeTopApp()); assertNotEquals(SCHED_GROUP_TOP_APP, host.mState.getSetSchedGroup()); } @SuppressWarnings("GuardedBy") @Test @EnableFlags(Flags.FLAG_NOT_SKIP_CONNECTION_RECOMPUTE_FOR_BIND_SCHEDULE_LIKE_TOP_APP) public void testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostPrivileged_notSkipConnectionCompute_hostGetsTopSchedGroup() { // Similar to its counter-part "withoutFlag" but when the feature flag // "not_skip_connection_recompute_for_bind_schedule_like_top_app" is enabled, the evaluation // of connection with BIND_SCHEDULE_LIKE_TOP_APP will not be skipped if the corresponding // flag has not yet been set. ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); mProcessStateController.setMaxAdj(host, PERSISTENT_SERVICE_ADJ); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, SYSTEM_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); assertTrue(host.mState.shouldScheduleLikeTopApp()); assertEquals(SCHED_GROUP_TOP_APP, host.mState.getCurrentSchedulingGroup()); } private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName, String packageName, boolean hasShownUi) { return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi( Loading Loading
services/core/java/com/android/server/am/OomAdjuster.java +1 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ALLOWLIST; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BACKUP; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SERVICE_BINDER_CALL; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BIND_SERVICE; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_COMPONENT_DISABLED; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_EXECUTING_SERVICE; Loading @@ -52,6 +51,7 @@ import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RECONFIGURATION import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SERVICE_BINDER_CALL; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHELL; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER; Loading
services/core/java/com/android/server/am/OomAdjusterImpl.java +45 −19 Original line number Diff line number Diff line Loading @@ -991,13 +991,12 @@ public class OomAdjusterImpl extends OomAdjuster { ConnectionRecord cr = psr.getConnectionAt(i); ProcessRecord service = cr.hasFlag(ServiceInfo.FLAG_ISOLATED_PROCESS) ? cr.binding.service.isolationHostProc : cr.binding.service.app; if (service == null || service == app || (service.mState.getMaxAdj() >= SYSTEM_ADJ && service.mState.getMaxAdj() < FOREGROUND_APP_ADJ) || (service.mState.getCurAdj() <= FOREGROUND_APP_ADJ && service.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && service.mState.getCurProcState() <= PROCESS_STATE_TOP) || (service.isSdkSandbox && cr.binding.attributedClient != null)) { if (service == null || service == app || isSandboxAttributedConnection(cr, service)) { continue; } // If the host is high priority, skip the connection recompute unless the connection has // flags, which needs extra consideration. e.g. BIND_SCHEDULE_LIKE_TOP_APP if (isHighPriorityProcess(service) && allowSkipForBindScheduleLikeTopApp(cr, service)) { continue; } connectionConsumer.accept(cr, service); Loading @@ -1006,12 +1005,10 @@ public class OomAdjusterImpl extends OomAdjuster { for (int i = psr.numberOfSdkSandboxConnections() - 1; i >= 0; i--) { final ConnectionRecord cr = psr.getSdkSandboxConnectionAt(i); final ProcessRecord service = cr.binding.service.app; if (service == null || service == app || (service.mState.getMaxAdj() >= SYSTEM_ADJ && service.mState.getMaxAdj() < FOREGROUND_APP_ADJ) || (service.mState.getCurAdj() <= FOREGROUND_APP_ADJ && service.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && service.mState.getCurProcState() <= PROCESS_STATE_TOP)) { if (service == null || service == app) { continue; } if (isHighPriorityProcess(service) && allowSkipForBindScheduleLikeTopApp(cr, service)) { continue; } connectionConsumer.accept(cr, service); Loading @@ -1021,18 +1018,47 @@ public class OomAdjusterImpl extends OomAdjuster { for (int i = ppr.numberOfProviderConnections() - 1; i >= 0; i--) { ContentProviderConnection cpc = ppr.getProviderConnectionAt(i); ProcessRecord provider = cpc.provider.proc; if (provider == null || provider == app || (provider.mState.getMaxAdj() >= ProcessList.SYSTEM_ADJ && provider.mState.getMaxAdj() < FOREGROUND_APP_ADJ) || (provider.mState.getCurAdj() <= FOREGROUND_APP_ADJ && provider.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && provider.mState.getCurProcState() <= PROCESS_STATE_TOP)) { if (provider == null || provider == app || isHighPriorityProcess(provider)) { continue; } connectionConsumer.accept(cpc, provider); } } /** * This is one of the condition that blocks the skipping of connection evaluation. This method * returns false when the given connection has flag {@link Context#BIND_SCHEDULE_LIKE_TOP_APP} * but the host process has not set the corresponding flag, * {@link ProcessStateRecord#mScheduleLikeTopApp}. */ private static boolean allowSkipForBindScheduleLikeTopApp(ConnectionRecord cr, ProcessRecord host) { // If feature flag for optionally blocking skipping is disabled. Always allow skipping. if (!Flags.notSkipConnectionRecomputeForBindScheduleLikeTopApp()) { return true; } // Need to check shouldScheduleLikeTopApp otherwise, there will be too many recompute which // leads to OOM. return !(cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP) && !host.mState.shouldScheduleLikeTopApp()); } private static boolean isSandboxAttributedConnection(ConnectionRecord cr, ProcessRecord host) { return host.isSdkSandbox && cr.binding.attributedClient != null; } private static boolean isHighPriorityProcess(ProcessRecord proc) { final boolean isPersistentSystemProcess = proc.mState.getMaxAdj() >= SYSTEM_ADJ && proc.mState.getMaxAdj() < FOREGROUND_APP_ADJ; final boolean isEffectivelyForeground = proc.mState.getCurAdj() <= FOREGROUND_APP_ADJ && proc.mState.getCurrentSchedulingGroup() > SCHED_GROUP_BACKGROUND && proc.mState.getCurProcState() <= PROCESS_STATE_TOP; return isPersistentSystemProcess || isEffectivelyForeground; } /** * Stream the connections from clients with {@code app} as the host to {@code * connectionConsumer}. Loading
services/core/java/com/android/server/am/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -258,3 +258,10 @@ flag { description: "Enable ActivityManagerStructured Service" bug: "419409018" } flag { name: "not_skip_connection_recompute_for_bind_schedule_like_top_app" namespace: "wear_frameworks" description: "If a connection has flag BIND_SCHEDULE_LIKE_TOP_APP but the host process has not set the corresponding flag, do not skip the connection recompute." bug: "417720000" }
services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +86 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP; import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP_BOUND; import static com.android.server.am.ProcessList.SERVICE_ADJ; import static com.android.server.am.ProcessList.SERVICE_B_ADJ; import static com.android.server.am.ProcessList.SYSTEM_ADJ; import static com.android.server.am.ProcessList.UNKNOWN_ADJ; import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ; import static com.android.server.wm.WindowProcessController.ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED; Loading Loading @@ -115,6 +116,7 @@ import android.os.PowerManagerInternal; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; Loading Loading @@ -3760,6 +3762,90 @@ public class MockingOomAdjusterTests { SCHED_GROUP_RESTRICTED); } @SuppressWarnings("GuardedBy") @Test public void testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostGetsTopSchedGroup() { // When system client binds a service with BIND_SCHEDULE_LIKE_TOP_APP, the service should // will be prioritized as top app. ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); host.mState.setCurrentSchedulingGroup(SCHED_GROUP_DEFAULT); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, SYSTEM_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); assertTrue(host.mState.shouldScheduleLikeTopApp()); assertEquals(SCHED_GROUP_TOP_APP, host.mState.getCurrentSchedulingGroup()); } @SuppressWarnings("GuardedBy") @Test public void testUpdateOomAdj_bindScheduleLikeTopApp_nonSystemClient_hostNotGetTopSchedGroup() { ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); assertFalse(host.mState.shouldScheduleLikeTopApp()); assertNotEquals(SCHED_GROUP_TOP_APP, host.mState.getCurrentSchedulingGroup()); } @SuppressWarnings("GuardedBy") @Test @DisableFlags(Flags.FLAG_NOT_SKIP_CONNECTION_RECOMPUTE_FOR_BIND_SCHEDULE_LIKE_TOP_APP) public void testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostPrivileged_skipConnectionCompute_hostNotGetTopSchedGroup() { // Similar to testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostGetsTopSchedGroup, // but now the host process is already marked as privileged(see // OomAdjusterImpl#isHighPriorityProcess for detail). In this case, connection evaluation // will be skipped, as a result, the scheduling group stays default. ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); mProcessStateController.setMaxAdj(host, PERSISTENT_SERVICE_ADJ); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, SYSTEM_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); // The update for host by its client connection evaluation is skipped. assertFalse(host.mState.shouldScheduleLikeTopApp()); assertNotEquals(SCHED_GROUP_TOP_APP, host.mState.getSetSchedGroup()); } @SuppressWarnings("GuardedBy") @Test @EnableFlags(Flags.FLAG_NOT_SKIP_CONNECTION_RECOMPUTE_FOR_BIND_SCHEDULE_LIKE_TOP_APP) public void testUpdateOomAdj_bindScheduleLikeTopApp_systemClient_hostPrivileged_notSkipConnectionCompute_hostGetsTopSchedGroup() { // Similar to its counter-part "withoutFlag" but when the feature flag // "not_skip_connection_recompute_for_bind_schedule_like_top_app" is enabled, the evaluation // of connection with BIND_SCHEDULE_LIKE_TOP_APP will not be skipped if the corresponding // flag has not yet been set. ProcessRecord host = makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true); mProcessStateController.setMaxAdj(host, PERSISTENT_SERVICE_ADJ); ProcessRecord client = makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false); mProcessStateController.setMaxAdj(client, SYSTEM_ADJ); bindService(host, client, null, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class)); updateOomAdj(client); assertTrue(host.mState.shouldScheduleLikeTopApp()); assertEquals(SCHED_GROUP_TOP_APP, host.mState.getCurrentSchedulingGroup()); } private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName, String packageName, boolean hasShownUi) { return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi( Loading