summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java122
-rw-r--r--services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java8
-rw-r--r--services/core/java/com/android/server/am/flags.aconfig10
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java269
4 files changed, 370 insertions, 39 deletions
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 42966a347aec..de3e2c90efe1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -4068,8 +4068,9 @@ public class OomAdjuster {
}
/**
- * Evaluate the service connection, return {@code true} if the client will change the state
- * of the service host process by the given connection.
+ * Evaluate the service connection, return {@code true} if the client will change any state
+ * (ie. ProcessState, oomAdj, capability, etc) of the service host process by the given
+ * connection.
*/
@GuardedBy("mService")
boolean evaluateServiceConnectionAdd(ProcessRecord client, ProcessRecord app,
@@ -4077,20 +4078,40 @@ public class OomAdjuster {
if (evaluateConnectionPrelude(client, app)) {
return true;
}
- if (app.getSetAdj() <= client.getSetAdj()
- && app.getSetProcState() <= client.getSetProcState()
- && ((app.getSetCapability() & client.getSetCapability())
- == client.getSetCapability()
- || cr.notHasFlag(Context.BIND_INCLUDE_CAPABILITIES
- | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS))) {
- // The service host process has better states than the client, so no change.
- return false;
+
+ boolean needDryRun = false;
+ if (app.getSetAdj() > client.getSetAdj()) {
+ // The connection might elevate the importance of the service's oom adj score.
+ needDryRun = true;
+ } else if (app.getSetProcState() > client.getSetProcState()) {
+ // The connection might elevate the importance of the service's process state.
+ needDryRun = true;
+ } else if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES
+ | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS)
+ && (app.getSetCapability() & client.getSetCapability())
+ != client.getSetCapability()) {
+ // The connection might elevate the importance of the service's capabilities.
+ needDryRun = true;
+ } else if (Flags.unfreezeBindPolicyFix()
+ && cr.hasFlag(Context.BIND_WAIVE_PRIORITY
+ | Context.BIND_ALLOW_OOM_MANAGEMENT)) {
+ // These bind flags can grant the shouldNotFreeze state to the service.
+ needDryRun = true;
+ } else if (Flags.unfreezeBindPolicyFix()
+ && client.mOptRecord.shouldNotFreeze()
+ && !app.mOptRecord.shouldNotFreeze()) {
+ // The shouldNotFreeze state can be propagated and needs to be checked.
+ needDryRun = true;
+ }
+
+ if (needDryRun) {
+ // Take a dry run of the computeServiceHostOomAdjLSP, this would't be expensive
+ // since it's only evaluating one service connection.
+ return computeServiceHostOomAdjLSP(cr, app, client, mInjector.getUptimeMillis(),
+ mService.getTopApp(), false, false, false, OOM_ADJ_REASON_NONE,
+ CACHED_APP_MIN_ADJ, false, true /* dryRun */);
}
- // Take a dry run of the computeServiceHostOomAdjLSP, this would't be expensive
- // since it's only evaluating one service connection.
- return computeServiceHostOomAdjLSP(cr, app, client, mInjector.getUptimeMillis(),
- mService.getTopApp(), false, false, false, OOM_ADJ_REASON_NONE,
- CACHED_APP_MIN_ADJ, false, true /* dryRun */);
+ return false;
}
@GuardedBy("mService")
@@ -4100,17 +4121,26 @@ public class OomAdjuster {
return true;
}
- if (app.getSetAdj() < client.getSetAdj()
- && app.getSetProcState() < client.getSetProcState()) {
- // The service host process has better states than the client.
- if (((app.getSetCapability() & client.getSetCapability()) == PROCESS_CAPABILITY_NONE)
- || cr.notHasFlag(Context.BIND_INCLUDE_CAPABILITIES
- | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS)) {
- // The service host app doesn't get any capabilities from the client.
- return false;
- }
+ if (app.getSetAdj() >= client.getSetAdj()) {
+ return true;
+ } else if (app.getSetProcState() >= client.getSetProcState()) {
+ return true;
+ } else if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES
+ | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS)
+ && (app.getSetCapability() & client.getSetCapability())
+ != PROCESS_CAPABILITY_NONE) {
+ return true;
+ } else if (Flags.unfreezeBindPolicyFix()
+ && cr.hasFlag(Context.BIND_WAIVE_PRIORITY
+ | Context.BIND_ALLOW_OOM_MANAGEMENT)) {
+ return true;
+ } else if (Flags.unfreezeBindPolicyFix()
+ && app.mOptRecord.shouldNotFreeze()
+ && client.mOptRecord.shouldNotFreeze()) {
+ // Process has shouldNotFreeze and it could have gotten it from the client.
+ return true;
}
- return true;
+ return false;
}
@GuardedBy("mService")
@@ -4118,14 +4148,25 @@ public class OomAdjuster {
if (evaluateConnectionPrelude(client, app)) {
return true;
}
- if (app.getSetAdj() <= client.getSetAdj()
- && app.getSetProcState() <= client.getSetProcState()) {
- // The provider host process has better states than the client, so no change.
- return false;
+
+ boolean needDryRun = false;
+ if (app.getSetAdj() > client.getSetAdj()) {
+ needDryRun = true;
+ } else if (app.getSetProcState() > client.getSetProcState()) {
+ needDryRun = true;
+ } else if (Flags.unfreezeBindPolicyFix()
+ && client.mOptRecord.shouldNotFreeze()
+ && !app.mOptRecord.shouldNotFreeze()) {
+ needDryRun = true;
+ }
+
+ if (needDryRun) {
+ return computeProviderHostOomAdjLSP(null, app, client, mInjector.getUptimeMillis(),
+ mService.getTopApp(), false, false, false, OOM_ADJ_REASON_NONE,
+ CACHED_APP_MIN_ADJ,
+ false, true /* dryRun */);
}
- return computeProviderHostOomAdjLSP(null, app, client, mInjector.getUptimeMillis(),
- mService.getTopApp(), false, false, false, OOM_ADJ_REASON_NONE, CACHED_APP_MIN_ADJ,
- false, true /* dryRun */);
+ return false;
}
@GuardedBy("mService")
@@ -4133,12 +4174,19 @@ public class OomAdjuster {
if (evaluateConnectionPrelude(client, app)) {
return true;
}
- if (app.getSetAdj() < client.getSetAdj()
- && app.getSetProcState() < client.getSetProcState()) {
- // The provider host process has better states than the client, so no change.
- return false;
+
+ if (app.getSetAdj() >= client.getSetAdj()) {
+ return true;
+ } else if (app.getSetProcState() >= client.getSetProcState()) {
+ return true;
+ } else if (Flags.unfreezeBindPolicyFix()
+ && app.mOptRecord.shouldNotFreeze()
+ && client.mOptRecord.shouldNotFreeze()) {
+ // Process has shouldNotFreeze and it could have gotten it from the client.
+ return true;
}
- return true;
+
+ return false;
}
private boolean evaluateConnectionPrelude(ProcessRecord client, ProcessRecord app) {
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index 57a5e3f0c302..980c1f587677 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -18,8 +18,8 @@ package com.android.server.am;
import android.annotation.IntDef;
import android.annotation.UptimeMillisLong;
-import android.app.ActivityManagerInternal.OomAdjReason;
import android.app.ActivityManagerInternal.FrozenProcessListener;
+import android.app.ActivityManagerInternal.OomAdjReason;
import android.util.Pair;
import android.util.TimeUtils;
@@ -338,7 +338,11 @@ final class ProcessCachedOptimizerRecord {
boolean setShouldNotFreeze(boolean shouldNotFreeze, boolean dryRun,
@ShouldNotFreezeReason int reason, int adjSeq) {
if (dryRun) {
- return mFrozen && !shouldNotFreeze;
+ if (Flags.unfreezeBindPolicyFix()) {
+ return mShouldNotFreeze != shouldNotFreeze;
+ } else {
+ return mFrozen && !shouldNotFreeze;
+ }
}
if (Flags.traceUpdateAppFreezeStateLsp()) {
if (shouldNotFreeze) {
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index d680712676cd..883482053490 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -241,3 +241,13 @@ flag {
is_fixed_read_only: true
bug: "369487976"
}
+
+flag {
+ name: "unfreeze_bind_policy_fix"
+ namespace: "backstage_power"
+ description: "Make sure shouldNotFreeze state change correctly triggers updates."
+ bug: "375691778"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} \ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java
index 59302ee408eb..2988c77703b7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java
@@ -22,6 +22,7 @@ import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_HOME;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
+import static android.content.Context.BIND_ALLOW_OOM_MANAGEMENT;
import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_INCLUDE_CAPABILITIES;
import static android.content.Context.BIND_WAIVE_PRIORITY;
@@ -29,6 +30,7 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEM
import static android.os.UserHandle.USER_SYSTEM;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
+import static com.android.server.am.ProcessCachedOptimizerRecord.SHOULD_NOT_FREEZE_REASON_NONE;
import static com.android.server.am.ProcessList.CACHED_APP_MIN_ADJ;
import static com.android.server.am.ProcessList.HOME_APP_ADJ;
import static com.android.server.am.ProcessList.PERCEPTIBLE_APP_ADJ;
@@ -63,6 +65,10 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -114,6 +120,8 @@ public final class ServiceBindingOomAdjPolicyTest {
public final ServiceThreadRule mServiceThreadRule = new ServiceThreadRule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private Context mContext;
private HandlerThread mHandlerThread;
@@ -317,6 +325,256 @@ public final class ServiceBindingOomAdjPolicyTest {
}
@Test
+ @RequiresFlagsEnabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX)
+ public void testServiceDistinctBindingOomAdjShouldNotFreeze() throws Exception {
+ // Enable the flags.
+ mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY);
+
+ // Verify that there should be at least 1 oom adj update
+ // because the shouldNotFreeze state needs to be propagated.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ (app) -> {
+ this.setHasForegroundServices(app);
+ this.setAllowListed(app);
+ },
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHomeProcess,
+ BIND_AUTO_CREATE,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be at least 1 oom adj update
+ // because the shouldNotFreeze state needs to be propagated.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ (app) -> {
+ this.setHomeProcess(app);
+ this.setAllowListed(app);
+ },
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_FOREGROUND_SERVICE,
+ PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHasForegroundServices,
+ BIND_AUTO_CREATE,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be at least 1 oom adj update
+ // because the client is more important (regardless of shouldNotFreeze state).
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ (app) -> {
+ this.setHasForegroundServices(app);
+ this.setAllowListed(app);
+ },
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ (app) -> {
+ this.setHomeProcess(app);
+ this.setAllowListed(app);
+ },
+ BIND_AUTO_CREATE,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be 0 oom adj update for binding
+ // because setShouldNotFreeze is already set
+ // but for the unbinding must update in case the binding could be the source of the
+ // shouldNotFreeze.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ (app) -> {
+ this.setHomeProcess(app);
+ this.setAllowListed(app);
+ },
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_FOREGROUND_SERVICE,
+ PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ (app) -> {
+ this.setHasForegroundServices(app);
+ this.setAllowListed(app);
+ },
+ BIND_AUTO_CREATE,
+ never(), atLeastOnce());
+
+
+ // Disable the flags.
+ mSetFlagsRule.disableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY);
+
+ // Verify that there should be at least 1 oom adj update
+ // because the client is more important.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ (app) -> {
+ this.setHasForegroundServices(app);
+ this.setAllowListed(app);
+ },
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHomeProcess,
+ BIND_AUTO_CREATE,
+ atLeastOnce(), atLeastOnce());
+ }
+
+ @Test
+ @RequiresFlagsEnabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX)
+ public void testServiceDistinctBindingOomAdjAllowOomManagement() throws Exception {
+ // Enable the flags.
+ mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY);
+
+ // Verify that there should be at least 1 oom adj update
+ // because BIND_ALLOW_OOM_MANAGEMENT sets the shouldNotFreeze state which needs to be
+ // propagated.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHasForegroundServices,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHomeProcess,
+ BIND_AUTO_CREATE | BIND_ALLOW_OOM_MANAGEMENT,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be at least 1 oom adj update
+ // because BIND_ALLOW_OOM_MANAGEMENT sets the shouldNotFreeze state which needs to be
+ // propagated.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHomeProcess,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_FOREGROUND_SERVICE,
+ PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHasForegroundServices,
+ BIND_AUTO_CREATE | BIND_ALLOW_OOM_MANAGEMENT,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be at least 1 oom adj update
+ // because the client is more important (regardless of BIND_ALLOW_OOM_MANAGEMENT).
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHasForegroundServices,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ (app) -> {
+ this.setHomeProcess(app);
+ this.setAllowListed(app);
+ },
+ BIND_AUTO_CREATE | BIND_ALLOW_OOM_MANAGEMENT,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be 0 oom adj update for binding
+ // because setShouldNotFreeze is already set
+ // but for the unbinding must update in case the BIND_ALLOW_OOM_MANAGEMENT maintaining the
+ // shouldNotFreeze.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHomeProcess,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_FOREGROUND_SERVICE,
+ PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ (app) -> {
+ this.setHasForegroundServices(app);
+ this.setAllowListed(app);
+ },
+ BIND_AUTO_CREATE | BIND_ALLOW_OOM_MANAGEMENT,
+ never(), atLeastOnce());
+
+
+ // Disable the flags.
+ mSetFlagsRule.disableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY);
+
+ // Verify that there should be at least 1 oom adj update
+ // because the client is more important.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHasForegroundServices,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHomeProcess,
+ BIND_AUTO_CREATE | BIND_ALLOW_OOM_MANAGEMENT,
+ atLeastOnce(), atLeastOnce());
+ }
+
+ @Test
+ @RequiresFlagsEnabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX)
+ public void testServiceDistinctBindingOomAdjWaivePriority_propagateUnfreeze() throws Exception {
+ // Enable the flags.
+ mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY);
+
+ // Verify that there should be at least 1 oom adj update
+ // because BIND_WAIVE_PRIORITY sets the shouldNotFreeze state which needs to be propagated.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHasForegroundServices,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHomeProcess,
+ BIND_AUTO_CREATE | BIND_WAIVE_PRIORITY,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be at least 1 oom adj update
+ // because BIND_WAIVE_PRIORITY sets the shouldNotFreeze state which needs to be propagated.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHomeProcess,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_FOREGROUND_SERVICE,
+ PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHasForegroundServices,
+ BIND_AUTO_CREATE | BIND_WAIVE_PRIORITY,
+ atLeastOnce(), atLeastOnce());
+
+ // Verify that there should be 0 oom adj update for binding
+ // because setShouldNotFreeze is already set
+ // but for the unbinding, because client is better than service, we can't skip it safely.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHasForegroundServices,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ (app) -> {
+ this.setHomeProcess(app);
+ this.setAllowListed(app);
+ },
+ BIND_AUTO_CREATE | BIND_WAIVE_PRIORITY,
+ never(), atLeastOnce());
+
+ // Verify that there should be 0 oom adj update for binding
+ // because setShouldNotFreeze is already set
+ // but for the unbinding must update in case the BIND_WAIVE_PRIORITY maintaining the
+ // shouldNotFreeze.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHomeProcess,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_FOREGROUND_SERVICE,
+ PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ (app) -> {
+ this.setHasForegroundServices(app);
+ this.setAllowListed(app);
+ },
+ BIND_AUTO_CREATE | BIND_WAIVE_PRIORITY,
+ never(), atLeastOnce());
+
+
+ // Disable the flags.
+ mSetFlagsRule.disableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY);
+
+ // Verify that there should be at least 1 oom adj update
+ // because the client is more important.
+ performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID,
+ PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ PROCESS_CAPABILITY_NONE, TEST_APP1_NAME,
+ this::setHasForegroundServices,
+ TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME,
+ HOME_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME,
+ this::setHomeProcess,
+ BIND_AUTO_CREATE | BIND_WAIVE_PRIORITY,
+ atLeastOnce(), atLeastOnce());
+ }
+
+ @Test
+ @RequiresFlagsDisabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX)
public void testServiceDistinctBindingOomAdjWaivePriority() throws Exception {
// Enable the flags.
mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY);
@@ -527,6 +785,15 @@ public final class ServiceBindingOomAdjPolicyTest {
}
@SuppressWarnings("GuardedBy")
+ private void setAllowListed(ProcessRecord app) {
+ final UidRecord uidRec = mock(UidRecord.class);
+ app.setUidRecord(uidRec);
+ doReturn(true).when(uidRec).isCurAllowListed();
+
+ app.mOptRecord.setShouldNotFreeze(true, SHOULD_NOT_FREEZE_REASON_NONE, 1234);
+ }
+
+ @SuppressWarnings("GuardedBy")
private ProcessRecord addProcessRecord(int pid, int uid, int procState, int adj, int cap,
String packageName) {
final ApplicationThreadDeferred appThread = mock(ApplicationThreadDeferred.class);
@@ -574,8 +841,10 @@ public final class ServiceBindingOomAdjPolicyTest {
String processName, String packageName, ActivityManagerService ams) {
final ProcessRecord app = ApplicationExitInfoTest.makeProcessRecord(pid, uid, packageUid,
definingUid, connectionGroup, procState, pss, rss, processName, packageName, ams);
+ app.mState.setCurRawProcState(procState);
app.mState.setCurProcState(procState);
app.mState.setSetProcState(procState);
+ app.mState.setCurRawAdj(adj);
app.mState.setCurAdj(adj);
app.mState.setSetAdj(adj);
app.mState.setCurCapability(cap);