summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/Context.java13
-rw-r--r--services/core/java/com/android/server/am/ConnectionRecord.java6
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java9
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java64
4 files changed, 88 insertions, 4 deletions
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4d56c1dcaa80..907db7df68d5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -513,10 +513,23 @@ public abstract class Context {
* restart. There is no guarantee this will be respected, as the system
* tries to balance such requests from one app vs. the importance of
* keeping other apps around.
+ *
+ * @deprecated Repurposed to {@link #BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE}.
*/
+ @Deprecated
public static final int BIND_VISIBLE = 0x10000000;
/**
+ * @hide Flag for {@link #bindService}: Treat the binding as hosting a foreground service
+ * and also visible to the user. That is, the app hosting the service will get its process state
+ * bumped to the {@link android.app.ActivityManager#PROCESS_STATE_FOREGROUND_SERVICE},
+ * and it's considered as visible to the user, thus less likely to be expunged from memory
+ * on low memory situations. This is intented for use by processes with the process state
+ * better than the {@link android.app.ActivityManager#PROCESS_STATE_TOP}.
+ */
+ public static final int BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE = 0x10000000;
+
+ /**
* @hide
* Flag for {@link #bindService}: Consider this binding to be causing the target
* process to be showing UI, so it will be do a UI_HIDDEN memory trim when it goes
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index b6757c8322d4..17fff919ba20 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -72,7 +72,7 @@ final class ConnectionRecord {
Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
Context.BIND_FOREGROUND_SERVICE,
Context.BIND_TREAT_LIKE_ACTIVITY,
- Context.BIND_VISIBLE,
+ Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
Context.BIND_SHOWING_UI,
Context.BIND_NOT_VISIBLE,
Context.BIND_NOT_PERCEPTIBLE,
@@ -225,8 +225,8 @@ final class ConnectionRecord {
if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0) {
sb.append("SLTA ");
}
- if ((flags&Context.BIND_VISIBLE) != 0) {
- sb.append("VIS ");
+ if ((flags & Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE) != 0) {
+ sb.append("VFGS ");
}
if ((flags&Context.BIND_SHOWING_UI) != 0) {
sb.append("UI ");
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 3ae8b980a311..e7fcc5989467 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -39,6 +39,7 @@ import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
+import static android.content.Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
@@ -2061,6 +2062,10 @@ public class OomAdjuster {
newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
newAdj = clientAdj;
+ } else if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)
+ && clientAdj <= ProcessList.VISIBLE_APP_ADJ
+ && adj > ProcessList.VISIBLE_APP_ADJ) {
+ newAdj = ProcessList.VISIBLE_APP_ADJ;
} else {
if (adj > ProcessList.VISIBLE_APP_ADJ) {
// TODO: Is this too limiting for apps bound from TOP?
@@ -2097,7 +2102,9 @@ public class OomAdjuster {
// processes). These should not bring the current process
// into the top state, since they are not on top. Instead
// give them the best bound state after that.
- if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
+ if (cr.hasFlag(BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) {
+ clientProcState = PROCESS_STATE_FOREGROUND_SERVICE;
+ } else if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
} else if (mService.mWakefulness.get()
== PowerManagerInternal.WAKEFULNESS_AWAKE
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 2f68306e9ba1..8d59dce29bd9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -30,6 +30,7 @@ import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
@@ -1591,6 +1592,69 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_DoOne_TreatLikeVisFGS() {
+ 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));
+ client1.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+ client2.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+
+ final ServiceRecord s1 = bindService(app1, client1, null,
+ Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE, mock(IBinder.class));
+ final ServiceRecord s2 = bindService(app2, client2, null,
+ Context.BIND_IMPORTANT, mock(IBinder.class));
+
+ sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
+ sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_PERSISTENT, PERSISTENT_SERVICE_ADJ,
+ SCHED_GROUP_DEFAULT);
+
+ bindService(app2, client1, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
+ mock(IBinder.class));
+ sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+ assertProcStates(app2, PROCESS_STATE_PERSISTENT, PERSISTENT_SERVICE_ADJ,
+ SCHED_GROUP_DEFAULT);
+
+ s1.getConnections().clear();
+ s2.getConnections().clear();
+ client1.mState.setMaxAdj(UNKNOWN_ADJ);
+ client2.mState.setMaxAdj(UNKNOWN_ADJ);
+ client1.mServices.setHasForegroundServices(true, 0);
+ client2.mState.setHasOverlayUi(true);
+
+ bindService(app1, client1, s1, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
+ mock(IBinder.class));
+ bindService(app2, client2, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
+ mock(IBinder.class));
+
+ sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
+ sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app2, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+
+ client2.mState.setHasOverlayUi(false);
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(client2).when(sService).getTopApp();
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+
+ sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+ assertProcStates(app2, PROCESS_STATE_BOUND_TOP, VISIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_UidIdle_StopService() {
final ProcessRecord app1 = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));