summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java10
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java40
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java18
-rw-r--r--services/core/java/com/android/server/am/ProcessServiceRecord.java75
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java67
6 files changed, 216 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2643bed44e2e..2c0514d7d0aa 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2894,6 +2894,12 @@ public final class ActiveServices {
s.isNotAppComponentUsage = true;
}
+ if (s.app != null && s.app.mState != null
+ && s.app.mState.getCurProcState() <= PROCESS_STATE_TOP
+ && (flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0) {
+ s.lastTopAlmostPerceptibleBindRequestUptimeMs = SystemClock.uptimeMillis();
+ }
+
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app.mServices, c, true);
}
@@ -4798,6 +4804,10 @@ public final class ActiveServices {
if ((c.flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
s.updateIsAllowedBgActivityStartsByBinding();
}
+ // And for almost perceptible exceptions.
+ if ((c.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0) {
+ psr.updateHasTopStartedAlmostPerceptibleServices();
+ }
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app.mServices, c, true);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 39a670ea7dbe..af9e410db6eb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -108,6 +108,8 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_PROCESS_START_ASYNC = "process_start_async";
static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
+ static final String KEY_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION =
+ "top_to_almost_perceptible_grace_duration";
static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold";
static final String KEY_MIN_CRASH_INTERVAL = "min_crash_interval";
static final String KEY_PROCESS_CRASH_COUNT_RESET_INTERVAL =
@@ -170,6 +172,7 @@ final class ActivityManagerConstants extends ContentObserver {
private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
+ private static final long DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION = 15 * 1000;
private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000;
private static final int DEFAULT_MIN_CRASH_INTERVAL = 2 * 60 * 1000;
private static final int DEFAULT_MAX_PHANTOM_PROCESSES = 32;
@@ -223,6 +226,8 @@ final class ActivityManagerConstants extends ContentObserver {
private static final int DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS = 10 * 1000;
+ private static final long DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS = 15 * 1000;
+
// Flag stored in the DeviceConfig API.
/**
* Maximum number of cached processes.
@@ -321,6 +326,9 @@ final class ActivityManagerConstants extends ContentObserver {
private static final String KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS =
"service_start_foreground_anr_delay_ms";
+ private static final String KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS =
+ "service_bind_almost_perceptible_timeout_ms";
+
// Maximum number of cached processes we will allow.
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -464,6 +472,13 @@ final class ActivityManagerConstants extends ContentObserver {
public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION;
/**
+ * Allow app just leaving TOP with an already running ALMOST_PERCEPTIBLE service to stay in
+ * a higher adj value for this long.
+ */
+ public long TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION =
+ DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION;
+
+ /**
* The minimum time we allow between crashes, for us to consider this
* application to be bad and stop its services and reject broadcasts.
* A reasonable interval here would be anything between 1-3 minutes.
@@ -654,6 +669,13 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS;
/**
+ * How long the grace period is from starting an almost perceptible service to a successful
+ * binding before we stop considering it an almost perceptible service.
+ */
+ volatile long mServiceBindAlmostPerceptibleTimeoutMs =
+ DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS;
+
+ /**
* Defines component aliases. Format
* ComponentName ":" ComponentName ( "," ComponentName ":" ComponentName )*
*/
@@ -942,6 +964,9 @@ final class ActivityManagerConstants extends ContentObserver {
case KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS:
updateServiceStartForegroundAnrDealyMs();
break;
+ case KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS:
+ updateServiceBindAlmostPerceptibleTimeoutMs();
+ break;
case KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED:
updateNoKillCachedProcessesUntilBootCompleted();
break;
@@ -1170,6 +1195,9 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_MEMORY_INFO_THROTTLE_TIME);
TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
DEFAULT_TOP_TO_FGS_GRACE_DURATION);
+ TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION = mParser.getDurationMillis(
+ KEY_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION,
+ DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION);
MIN_CRASH_INTERVAL = mParser.getInt(KEY_MIN_CRASH_INTERVAL,
DEFAULT_MIN_CRASH_INTERVAL);
PENDINGINTENT_WARNING_THRESHOLD = mParser.getInt(KEY_PENDINGINTENT_WARNING_THRESHOLD,
@@ -1432,6 +1460,14 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS);
}
+ private void updateServiceBindAlmostPerceptibleTimeoutMs() {
+ mServiceBindAlmostPerceptibleTimeoutMs = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS,
+ DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS);
+ }
+
+
private long[] parseLongArray(@NonNull String key, @NonNull long[] def) {
final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
key, null);
@@ -1647,6 +1683,8 @@ final class ActivityManagerConstants extends ContentObserver {
pw.println(MEMORY_INFO_THROTTLE_TIME);
pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("=");
pw.println(TOP_TO_FGS_GRACE_DURATION);
+ pw.print(" "); pw.print(KEY_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION); pw.print("=");
+ pw.println(TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION);
pw.print(" "); pw.print(KEY_MIN_CRASH_INTERVAL); pw.print("=");
pw.println(MIN_CRASH_INTERVAL);
pw.print(" "); pw.print(KEY_PROCESS_CRASH_COUNT_RESET_INTERVAL); pw.print("=");
@@ -1716,6 +1754,8 @@ final class ActivityManagerConstants extends ContentObserver {
pw.print("="); pw.println(mServiceStartForegroundTimeoutMs);
pw.print(" "); pw.print(KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS);
pw.print("="); pw.println(mServiceStartForegroundAnrDelayMs);
+ pw.print(" "); pw.print(KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS);
+ pw.print("="); pw.println(mServiceBindAlmostPerceptibleTimeoutMs);
pw.println();
if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index d6351527de6d..02206ffc7bef 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1674,6 +1674,24 @@ public class OomAdjuster {
}
}
+ // If the app was recently in the foreground and has expedited jobs running,
+ // allow it to get a higher rank in memory for some time, compared to other EJS and even
+ // foreground services so that it can finish performing any persistence/processing of
+ // in-memory state.
+ if (psr.hasTopStartedAlmostPerceptibleServices()
+ && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
+ && (state.getLastTopTime()
+ + mConstants.TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION > now
+ || state.getSetProcState() <= PROCESS_STATE_TOP)) {
+ adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
+ // This shall henceforth be called the "EJ" exemption, despite utilizing the
+ // ALMOST_PERCEPTIBLE flag to work.
+ state.setAdjType("top-ej-act");
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg for EJ: " + app);
+ }
+ }
+
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
if (state.getForcingToImportant() != null) {
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 8f77b87f5308..6b748193c123 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -19,6 +19,7 @@ package com.android.server.am;
import android.app.ActivityManager;
import android.content.Context;
import android.os.IBinder;
+import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -42,6 +43,18 @@ final class ProcessServiceRecord {
private boolean mHasForegroundServices;
/**
+ * Running any services that are almost perceptible (started with
+ * {@link Context#BIND_ALMOST_PERCEPTIBLE} while the app was on TOP)?
+ */
+ private boolean mHasTopStartedAlmostPerceptibleServices;
+
+ /**
+ * The latest value of {@link ServiceRecord#lastTopAlmostPerceptibleBindRequestUptimeMs} among
+ * the currently running services.
+ */
+ private long mLastTopStartedAlmostPerceptibleBindRequestUptimeMs;
+
+ /**
* Service that applied current connectionGroup/Importance.
*/
private ServiceRecord mConnectionService;
@@ -146,6 +159,46 @@ final class ProcessServiceRecord {
mRepFgServiceTypes = foregroundServiceTypes;
}
+ void updateHasTopStartedAlmostPerceptibleServices() {
+ mHasTopStartedAlmostPerceptibleServices = false;
+ mLastTopStartedAlmostPerceptibleBindRequestUptimeMs = 0;
+ for (int s = mServices.size() - 1; s >= 0; --s) {
+ final ServiceRecord sr = mServices.valueAt(s);
+ mLastTopStartedAlmostPerceptibleBindRequestUptimeMs = Math.max(
+ mLastTopStartedAlmostPerceptibleBindRequestUptimeMs,
+ sr.lastTopAlmostPerceptibleBindRequestUptimeMs);
+ if (!mHasTopStartedAlmostPerceptibleServices && isAlmostPerceptible(sr)) {
+ mHasTopStartedAlmostPerceptibleServices = true;
+ }
+ }
+ }
+
+ private boolean isAlmostPerceptible(ServiceRecord record) {
+ if (record.lastTopAlmostPerceptibleBindRequestUptimeMs <= 0) {
+ return false;
+ }
+ final ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections =
+ record.getConnections();
+ for (int m = serviceConnections.size() - 1; m >= 0; --m) {
+ final ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(m);
+
+ for (int c = clist.size() - 1; c >= 0; --c) {
+ final ConnectionRecord cr = clist.get(c);
+ if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean hasTopStartedAlmostPerceptibleServices() {
+ return mHasTopStartedAlmostPerceptibleServices
+ || (mLastTopStartedAlmostPerceptibleBindRequestUptimeMs > 0
+ && SystemClock.uptimeMillis() - mLastTopStartedAlmostPerceptibleBindRequestUptimeMs
+ < mService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs);
+ }
+
ServiceRecord getConnectionService() {
return mConnectionService;
}
@@ -243,6 +296,14 @@ final class ProcessServiceRecord {
if (added && record.serviceInfo != null) {
mApp.getWindowProcessController().onServiceStarted(record.serviceInfo);
}
+ if (record.lastTopAlmostPerceptibleBindRequestUptimeMs > 0) {
+ mLastTopStartedAlmostPerceptibleBindRequestUptimeMs = Math.max(
+ mLastTopStartedAlmostPerceptibleBindRequestUptimeMs,
+ record.lastTopAlmostPerceptibleBindRequestUptimeMs);
+ if (!mHasTopStartedAlmostPerceptibleServices) {
+ mHasTopStartedAlmostPerceptibleServices = isAlmostPerceptible(record);
+ }
+ }
return added;
}
@@ -253,7 +314,11 @@ final class ProcessServiceRecord {
* @return true if the service was removed, false otherwise.
*/
boolean stopService(ServiceRecord record) {
- return mServices.remove(record);
+ final boolean removed = mServices.remove(record);
+ if (record.lastTopAlmostPerceptibleBindRequestUptimeMs > 0) {
+ updateHasTopStartedAlmostPerceptibleServices();
+ }
+ return removed;
}
/**
@@ -261,6 +326,7 @@ final class ProcessServiceRecord {
*/
void stopAllServices() {
mServices.clear();
+ updateHasTopStartedAlmostPerceptibleServices();
}
/**
@@ -408,6 +474,13 @@ final class ProcessServiceRecord {
pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices);
pw.print(" forcingToImportant="); pw.println(mApp.mState.getForcingToImportant());
}
+ if (mHasTopStartedAlmostPerceptibleServices
+ || mLastTopStartedAlmostPerceptibleBindRequestUptimeMs > 0) {
+ pw.print(prefix); pw.print("mHasTopStartedAlmostPerceptibleServices=");
+ pw.print(mHasTopStartedAlmostPerceptibleServices);
+ pw.print(" mLastTopStartedAlmostPerceptibleBindRequestUptimeMs=");
+ pw.println(mLastTopStartedAlmostPerceptibleBindRequestUptimeMs);
+ }
if (mHasClientActivities || mHasAboveClient || mTreatLikeActivity) {
pw.print(prefix); pw.print("hasClientActivities="); pw.print(mHasClientActivities);
pw.print(" hasAboveClient="); pw.print(mHasAboveClient);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 795311f019a4..639f56cb12dd 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -24,6 +24,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.IApplicationThread;
import android.app.Notification;
@@ -141,6 +142,12 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
int pendingConnectionGroup; // To be filled in to ProcessRecord once it connects
int pendingConnectionImportance; // To be filled in to ProcessRecord once it connects
+ /**
+ * The last time (in uptime timebase) a bind request was made with BIND_ALMOST_PERCEPTIBLE for
+ * this service while on TOP.
+ */
+ long lastTopAlmostPerceptibleBindRequestUptimeMs;
+
// any current binding to this service has BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS flag?
private boolean mIsAllowedBgActivityStartsByBinding;
// is this service currently allowed to start activities from background by providing
@@ -713,6 +720,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
}
+ @NonNull
ArrayMap<IBinder, ArrayList<ConnectionRecord>> getConnections() {
return connections;
}
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 50a0a687603c..c747a5fd982b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -63,6 +63,7 @@ import static com.android.server.am.ProcessList.UNKNOWN_ADJ;
import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalAnswers.answer;
import static org.mockito.Mockito.any;
@@ -444,7 +445,7 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
- public void testUpdateOomAdj_DoOne_PerceptibleRecent() {
+ public void testUpdateOomAdj_DoOne_PerceptibleRecent_FgService() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
app.mServices.setHasForegroundServices(true, 0);
@@ -458,6 +459,70 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_DoOne_PerceptibleRecent_AlmostPerceptibleService() {
+ // Grace period allows the adjustment.
+ {
+ ProcessRecord system = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
+ long nowUptime = SystemClock.uptimeMillis();
+ app.mState.setLastTopTime(nowUptime);
+ // Simulate the system starting and binding to a service in the app.
+ ServiceRecord s = bindService(app, system,
+ null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+ s.lastTopAlmostPerceptibleBindRequestUptimeMs = nowUptime;
+ s.getConnections().clear();
+ app.mServices.updateHasTopStartedAlmostPerceptibleServices();
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+ }
+
+ // Out of grace period but valid binding allows the adjustment.
+ {
+ ProcessRecord system = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
+ long nowUptime = SystemClock.uptimeMillis();
+ app.mState.setLastTopTime(nowUptime);
+ // Simulate the system starting and binding to a service in the app.
+ ServiceRecord s = bindService(app, system,
+ null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+ s.lastTopAlmostPerceptibleBindRequestUptimeMs =
+ nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
+ app.mServices.updateHasTopStartedAlmostPerceptibleServices();
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+ }
+
+ // Out of grace period and no valid binding so no adjustment.
+ {
+ ProcessRecord system = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
+ long nowUptime = SystemClock.uptimeMillis();
+ app.mState.setLastTopTime(nowUptime);
+ // Simulate the system starting and binding to a service in the app.
+ ServiceRecord s = bindService(app, system,
+ null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+ s.lastTopAlmostPerceptibleBindRequestUptimeMs =
+ nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
+ s.getConnections().clear();
+ app.mServices.updateHasTopStartedAlmostPerceptibleServices();
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertNotEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+ }
+ }
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_DoOne_Toast() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));