Add new onUidProcAdjChanged callback to be consumed by the camera
service.
The camera service needs to know when individual process oom adj scores
are changed in order to address bug #124224342. When two separate
processes are displayed in split screen and focus is switched between
them, both proc states will remain the same while their oom scores
change. This is a problem if both have access to the camera - we want
only one owner of the camera stream at any given time and for the app
in focus to be the one to own it.
This patch adds a new IUidObserver registration level for individual
process oom score changes. In addition a new callback has been added to
IUidObserver to track these changes.
Change-Id: I68d964f474d20f819f54b614a4e314ce00aac8fb
Bug: 124224342
Test: -- ActivityManagerServiceTest
-- ActivityManagerProcessStateTest
-- ActivityManagerFgsBgStartTest
-- UidObserverControllerTest
-- NetworkPolicyManagerServiceTest
-- ShortcutManagerTest2
-- HintManagerServiceTest
-- VibrationSettingsTest
-- CameraEvictionTest#testCamera2AccessCallbackInSplitMode (x100)
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
index 70d5038..fab5b5f 100644
--- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
+++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
@@ -767,6 +767,10 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) {
+ }
}
private final class AppOpsWatcher extends IAppOpsCallback.Stub {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 2028be7..c4caa6c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1009,6 +1009,9 @@
@Override public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override public void onUidProcAdjChanged(int uid) {
+ }
};
public Context getTestableContext() {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index ee0f9e8..b3e81cb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -404,6 +404,10 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) {
+ }
}
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
index 5ec2f56..3578c8a 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
@@ -97,6 +97,10 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) {
+ }
};
ProcessStateModifier(@NonNull InternalResourceService irs) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5b05b45..7aefbae 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -222,6 +222,9 @@
@Override public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override public void onUidProcAdjChanged(int uid) {
+ }
}
final ArrayMap<OnUidImportanceListener, UidObserver> mImportanceListeners = new ArrayMap<>();
@@ -825,6 +828,9 @@
/** @hide Flag for registerUidObserver: report uid capability has changed. */
public static final int UID_OBSERVER_CAPABILITY = 1<<5;
+ /** @hide Flag for registerUidObserver: report pid oom adj has changed. */
+ public static final int UID_OBSERVER_PROC_OOM_ADJ = 1 << 6;
+
/** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: normal free-to-run operation. */
public static final int APP_START_MODE_NORMAL = 0;
diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl
index 74018a8..0c920f1 100644
--- a/core/java/android/app/IUidObserver.aidl
+++ b/core/java/android/app/IUidObserver.aidl
@@ -54,6 +54,13 @@
*/
void onUidStateChanged(int uid, int procState, long procStateSeq, int capability);
+ /**
+ * Report a proc oom adj change associated with a uid.
+ *
+ * @param uid The uid for which the state change is being reported.
+ */
+ void onUidProcAdjChanged(int uid);
+
// =============== End of transactions used on native side as well ============================
/**
diff --git a/core/proto/android/app/activitymanager.proto b/core/proto/android/app/activitymanager.proto
index a21d1d4..8d8759f 100644
--- a/core/proto/android/app/activitymanager.proto
+++ b/core/proto/android/app/activitymanager.proto
@@ -35,4 +35,6 @@
UID_OBSERVER_FLAG_CACHED = 5;
// report uid capability has changed, original value is 1 << 5
UID_OBSERVER_FLAG_CAPABILITY = 6;
+ // report pid oom adj has changed, original value is 1 << 6
+ UID_OBSERVER_FLAG_PROC_OOM_ADJ = 7;
}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 2bb8912..7205dd8 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -780,6 +780,7 @@
CHANGE_UNCACHED = 4;
CHANGE_CAPABILITY = 5;
CHANGE_PROCSTATE = 6;
+ CHANGE_PROCADJ = 7;
}
repeated Change last_reported_changes = 8;
optional int32 num_procs = 9;
diff --git a/native/android/activity_manager.cpp b/native/android/activity_manager.cpp
index 82f4569..155a355 100644
--- a/native/android/activity_manager.cpp
+++ b/native/android/activity_manager.cpp
@@ -45,6 +45,7 @@
void onUidIdle(uid_t uid, bool disabled) override;
void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
int32_t capability) override;
+ void onUidProcAdjChanged(uid_t uid) override;
// IBinder::DeathRecipient implementation
void binderDied(const wp<IBinder>& who) override;
@@ -120,6 +121,8 @@
void UidObserver::onUidIdle(uid_t uid __unused, bool disabled __unused) {}
+void UidObserver::onUidProcAdjChanged(uid_t uid __unused) {}
+
void UidObserver::onUidStateChanged(uid_t uid, int32_t procState,
int64_t procStateSeq __unused,
int32_t capability __unused) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index 6ee65ae..ec44f18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -394,6 +394,7 @@
override fun onUidActive(uid: Int) {}
override fun onUidIdle(uid: Int, disabled: Boolean) {}
override fun onUidCachedChanged(uid: Int, cached: Boolean) {}
+ override fun onUidProcAdjChanged(uid: Int) {}
}
}
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 16ff167..c5eb25b 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -385,6 +385,10 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) throws RemoteException {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) throws RemoteException {
+ }
}, UID_OBSERVER_GONE | UID_OBSERVER_ACTIVE, 0, null);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to register uid observer", e);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 45f06c74..1521861 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15257,7 +15257,7 @@
}
if ((enqueuedChange & UidRecord.CHANGE_GONE) != 0) {
mLocalPowerManager.uidGone(uid);
- } else {
+ } else if ((enqueuedChange & UidRecord.CHANGE_PROCSTATE) != 0) {
mLocalPowerManager.updateUidProcState(uid, procState);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 2b61e7f..1d39d4a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1671,6 +1671,10 @@
}
@Override
+ public void onUidProcAdjChanged(int uid) throws RemoteException {
+ }
+
+ @Override
public void onOomAdjMessage(String msg) {
synchronized (this) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 41ff083..d758a7f 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -908,6 +908,10 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) {
+ }
};
/**
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 85d3d5d..85f2a92 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1191,70 +1191,88 @@
}
for (int i = activeUids.size() - 1; i >= 0; i--) {
final UidRecord uidRec = activeUids.valueAt(i);
- int uidChange = 0;
- if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
- && (uidRec.getSetProcState() != uidRec.getCurProcState()
- || uidRec.getSetCapability() != uidRec.getCurCapability()
- || uidRec.isSetAllowListed() != uidRec.isCurAllowListed())) {
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec
- + ": proc state from " + uidRec.getSetProcState() + " to "
- + uidRec.getCurProcState() + ", capability from "
- + uidRec.getSetCapability() + " to " + uidRec.getCurCapability()
- + ", allowlist from " + uidRec.isSetAllowListed()
- + " to " + uidRec.isCurAllowListed());
- if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
- && !uidRec.isCurAllowListed()) {
- // UID is now in the background (and not on the temp allowlist). Was it
- // previously in the foreground (or on the temp allowlist)?
- if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState())
- || uidRec.isSetAllowListed()) {
- uidRec.setLastBackgroundTime(nowElapsed);
- if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
- // Note: the background settle time is in elapsed realtime, while
- // the handler time base is uptime. All this means is that we may
- // stop background uids later than we had intended, but that only
- // happens because the device was sleeping so we are okay anyway.
- mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
- mConstants.BACKGROUND_SETTLE_TIME);
+ if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT) {
+ if (uidRec.getSetProcState() != uidRec.getCurProcState()
+ || uidRec.getSetCapability() != uidRec.getCurCapability()
+ || uidRec.isSetAllowListed() != uidRec.isCurAllowListed()
+ || uidRec.getProcAdjChanged()) {
+ int uidChange = 0;
+ if (DEBUG_UID_OBSERVERS) {
+ Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec
+ + ": proc state from " + uidRec.getSetProcState() + " to "
+ + uidRec.getCurProcState() + ", capability from "
+ + uidRec.getSetCapability() + " to " + uidRec.getCurCapability()
+ + ", allowlist from " + uidRec.isSetAllowListed()
+ + " to " + uidRec.isCurAllowListed()
+ + ", procAdjChanged: " + uidRec.getProcAdjChanged());
+ }
+ if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
+ && !uidRec.isCurAllowListed()) {
+ // UID is now in the background (and not on the temp allowlist). Was it
+ // previously in the foreground (or on the temp allowlist)?
+ if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState())
+ || uidRec.isSetAllowListed()) {
+ uidRec.setLastBackgroundTime(nowElapsed);
+ if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
+ // Note: the background settle time is in elapsed realtime, while
+ // the handler time base is uptime. All this means is that we may
+ // stop background uids later than we had intended, but that only
+ // happens because the device was sleeping so we are okay anyway.
+ mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
+ mConstants.BACKGROUND_SETTLE_TIME);
+ }
}
+ if (uidRec.isIdle() && !uidRec.isSetIdle()) {
+ uidChange |= UidRecord.CHANGE_IDLE;
+ becameIdle.add(uidRec);
+ }
+ } else {
+ if (uidRec.isIdle()) {
+ uidChange |= UidRecord.CHANGE_ACTIVE;
+ EventLogTags.writeAmUidActive(uidRec.getUid());
+ uidRec.setIdle(false);
+ }
+ uidRec.setLastBackgroundTime(0);
}
- if (uidRec.isIdle() && !uidRec.isSetIdle()) {
- uidChange |= UidRecord.CHANGE_IDLE;
- becameIdle.add(uidRec);
+ final boolean wasCached = uidRec.getSetProcState()
+ > ActivityManager.PROCESS_STATE_RECEIVER;
+ final boolean isCached = uidRec.getCurProcState()
+ > ActivityManager.PROCESS_STATE_RECEIVER;
+ if (wasCached != isCached
+ || uidRec.getSetProcState() == PROCESS_STATE_NONEXISTENT) {
+ uidChange |= isCached ? UidRecord.CHANGE_CACHED :
+ UidRecord.CHANGE_UNCACHED;
}
- } else {
- if (uidRec.isIdle()) {
- uidChange |= UidRecord.CHANGE_ACTIVE;
- EventLogTags.writeAmUidActive(uidRec.getUid());
- uidRec.setIdle(false);
+ if (uidRec.getSetCapability() != uidRec.getCurCapability()) {
+ uidChange |= UidRecord.CHANGE_CAPABILITY;
}
- uidRec.setLastBackgroundTime(0);
- }
- final boolean wasCached = uidRec.getSetProcState()
- > ActivityManager.PROCESS_STATE_RECEIVER;
- final boolean isCached = uidRec.getCurProcState()
- > ActivityManager.PROCESS_STATE_RECEIVER;
- if (wasCached != isCached
- || uidRec.getSetProcState() == PROCESS_STATE_NONEXISTENT) {
- uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED;
- }
- if (uidRec.getSetCapability() != uidRec.getCurCapability()) {
- uidChange |= UidRecord.CHANGE_CAPABILITY;
- }
- if (uidRec.getSetProcState() != uidRec.getCurProcState()) {
- uidChange |= UidRecord.CHANGE_PROCSTATE;
- }
- uidRec.setSetProcState(uidRec.getCurProcState());
- uidRec.setSetCapability(uidRec.getCurCapability());
- uidRec.setSetAllowListed(uidRec.isCurAllowListed());
- uidRec.setSetIdle(uidRec.isIdle());
- mService.mAtmInternal.onUidProcStateChanged(
- uidRec.getUid(), uidRec.getSetProcState());
- mService.enqueueUidChangeLocked(uidRec, -1, uidChange);
- mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState(),
- uidRec.getCurCapability());
- if (uidRec.hasForegroundServices()) {
- mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
+ if (uidRec.getSetProcState() != uidRec.getCurProcState()) {
+ uidChange |= UidRecord.CHANGE_PROCSTATE;
+ }
+ if (uidRec.getProcAdjChanged()) {
+ uidChange |= UidRecord.CHANGE_PROCADJ;
+ }
+ uidRec.setSetProcState(uidRec.getCurProcState());
+ uidRec.setSetCapability(uidRec.getCurCapability());
+ uidRec.setSetAllowListed(uidRec.isCurAllowListed());
+ uidRec.setSetIdle(uidRec.isIdle());
+ uidRec.clearProcAdjChanged();
+ if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0
+ || (uidChange & UidRecord.CHANGE_CAPABILITY) != 0) {
+ mService.mAtmInternal.onUidProcStateChanged(
+ uidRec.getUid(), uidRec.getSetProcState());
+ }
+ if (uidChange != 0) {
+ mService.enqueueUidChangeLocked(uidRec, -1, uidChange);
+ }
+ if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0
+ || (uidChange & UidRecord.CHANGE_CAPABILITY) != 0) {
+ mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState(),
+ uidRec.getCurCapability());
+ }
+ if (uidRec.hasForegroundServices()) {
+ mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
+ }
}
}
mService.mInternal.deletePendingTopUid(uidRec.getUid());
@@ -2513,6 +2531,7 @@
long nowElapsed) {
boolean success = true;
final ProcessStateRecord state = app.mState;
+ final UidRecord uidRec = app.getUidRecord();
if (state.getCurRawAdj() != state.getSetRawAdj()) {
state.setSetRawAdj(state.getCurRawAdj());
@@ -2551,6 +2570,9 @@
reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
}
state.setSetAdj(state.getCurAdj());
+ if (uidRec != null) {
+ uidRec.noteProcAdjChanged();
+ }
state.setVerifiedAdj(ProcessList.INVALID_ADJ);
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a8612fd..6629a30 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -180,22 +180,22 @@
// OOM adjustments for processes in various states:
// Uninitialized value for any major or minor adj fields
- static final int INVALID_ADJ = -10000;
+ public static final int INVALID_ADJ = -10000;
// Adjustment used in certain places where we don't know it yet.
// (Generally this is something that is going to be cached, but we
// don't know the exact value in the cached range to assign yet.)
- static final int UNKNOWN_ADJ = 1001;
+ public static final int UNKNOWN_ADJ = 1001;
// This is a process only hosting activities that are not visible,
// so it can be killed without any disruption.
- static final int CACHED_APP_MAX_ADJ = 999;
- static final int CACHED_APP_MIN_ADJ = 900;
+ public static final int CACHED_APP_MAX_ADJ = 999;
+ public static final int CACHED_APP_MIN_ADJ = 900;
// This is the oom_adj level that we allow to die first. This cannot be equal to
// CACHED_APP_MAX_ADJ unless processes are actively being assigned an oom_score_adj of
// CACHED_APP_MAX_ADJ.
- static final int CACHED_APP_LMK_FIRST_ADJ = 950;
+ public static final int CACHED_APP_LMK_FIRST_ADJ = 950;
// Number of levels we have available for different service connection group importance
// levels.
@@ -203,7 +203,7 @@
// The B list of SERVICE_ADJ -- these are the old and decrepit
// services that aren't as shiny and interesting as the ones in the A list.
- static final int SERVICE_B_ADJ = 800;
+ public static final int SERVICE_B_ADJ = 800;
// This is the process of the previous application that the user was in.
// This process is kept above other things, because it is very common to
@@ -211,68 +211,68 @@
// task switch (toggling between the two top recent apps) as well as normal
// UI flow such as clicking on a URI in the e-mail app to view in the browser,
// and then pressing back to return to e-mail.
- static final int PREVIOUS_APP_ADJ = 700;
+ public static final int PREVIOUS_APP_ADJ = 700;
// This is a process holding the home application -- we want to try
// avoiding killing it, even if it would normally be in the background,
// because the user interacts with it so much.
- static final int HOME_APP_ADJ = 600;
+ public static final int HOME_APP_ADJ = 600;
// This is a process holding an application service -- killing it will not
// have much of an impact as far as the user is concerned.
- static final int SERVICE_ADJ = 500;
+ public static final int SERVICE_ADJ = 500;
// This is a process with a heavy-weight application. It is in the
// background, but we want to try to avoid killing it. Value set in
// system/rootdir/init.rc on startup.
- static final int HEAVY_WEIGHT_APP_ADJ = 400;
+ public static final int HEAVY_WEIGHT_APP_ADJ = 400;
// This is a process currently hosting a backup operation. Killing it
// is not entirely fatal but is generally a bad idea.
- static final int BACKUP_APP_ADJ = 300;
+ public static final int BACKUP_APP_ADJ = 300;
// This is a process bound by the system (or other app) that's more important than services but
// not so perceptible that it affects the user immediately if killed.
- static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
+ public static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
// This is a process hosting services that are not perceptible to the user but the
// client (system) binding to it requested to treat it as if it is perceptible and avoid killing
// it if possible.
- static final int PERCEPTIBLE_MEDIUM_APP_ADJ = 225;
+ public static final int PERCEPTIBLE_MEDIUM_APP_ADJ = 225;
// This is a process only hosting components that are perceptible to the
// user, and we really want to avoid killing them, but they are not
// immediately visible. An example is background music playback.
- static final int PERCEPTIBLE_APP_ADJ = 200;
+ public static final int PERCEPTIBLE_APP_ADJ = 200;
// This is a process only hosting activities that are visible to the
// user, so we'd prefer they don't disappear.
- static final int VISIBLE_APP_ADJ = 100;
+ public static final int VISIBLE_APP_ADJ = 100;
static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;
// This is a process that was recently TOP and moved to FGS. Continue to treat it almost
// like a foreground app for a while.
// @see TOP_TO_FGS_GRACE_PERIOD
- static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
+ public static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
// This is the process running the current foreground app. We'd really
// rather not kill it!
- static final int FOREGROUND_APP_ADJ = 0;
+ public static final int FOREGROUND_APP_ADJ = 0;
// This is a process that the system or a persistent process has bound to,
// and indicated it is important.
- static final int PERSISTENT_SERVICE_ADJ = -700;
+ public static final int PERSISTENT_SERVICE_ADJ = -700;
// This is a system persistent process, such as telephony. Definitely
// don't want to kill it, but doing so is not completely fatal.
- static final int PERSISTENT_PROC_ADJ = -800;
+ public static final int PERSISTENT_PROC_ADJ = -800;
// The system process runs at the default adjustment.
- static final int SYSTEM_ADJ = -900;
+ public static final int SYSTEM_ADJ = -900;
// Special code for native processes that are not being managed by the system (so
// don't have an oom adj assigned by the system).
- static final int NATIVE_ADJ = -1000;
+ public static final int NATIVE_ADJ = -1000;
// Memory pages are 4K.
static final int PAGE_SIZE = 4 * 1024;
@@ -5383,5 +5383,9 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) {
+ }
};
}
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index c3a232a..e42dac4 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -157,6 +157,9 @@
if ((pendingChange & UidRecord.CHANGE_PROCSTATE) != 0) {
currentChange |= UidRecord.CHANGE_PROCSTATE;
}
+ if ((pendingChange & UidRecord.CHANGE_PROCADJ) != 0) {
+ currentChange |= UidRecord.CHANGE_PROCADJ;
+ }
return currentChange;
}
@@ -248,6 +251,7 @@
try {
for (int j = 0; j < changesSize; j++) {
final ChangeRecord item = mActiveUidChanges[j];
+ final long start = SystemClock.uptimeMillis();
final int change = item.change;
if (change == UidRecord.CHANGE_PROCSTATE
&& (reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) == 0) {
@@ -255,7 +259,12 @@
// interested in all proc state changes.
continue;
}
- final long start = SystemClock.uptimeMillis();
+ if (change == UidRecord.CHANGE_PROCADJ
+ && (reg.mWhich & ActivityManager.UID_OBSERVER_PROC_OOM_ADJ) == 0) {
+ // No-op common case: no significant change, the observer is not
+ // interested in proc adj changes.
+ continue;
+ }
if ((change & UidRecord.CHANGE_IDLE) != 0) {
if ((reg.mWhich & ActivityManager.UID_OBSERVER_IDLE) != 0) {
if (DEBUG_UID_OBSERVERS) {
@@ -322,7 +331,12 @@
reg.mLastProcStates.put(item.uid, item.procState);
}
observer.onUidStateChanged(item.uid, item.procState,
- item.procStateSeq, item.capability);
+ item.procStateSeq,
+ item.capability);
+ }
+ if ((reg.mWhich & ActivityManager.UID_OBSERVER_PROC_OOM_ADJ) != 0
+ && (change & UidRecord.CHANGE_PROCADJ) != 0) {
+ observer.onUidProcAdjChanged(item.uid);
}
}
final int duration = (int) (SystemClock.uptimeMillis() - start);
@@ -443,6 +457,7 @@
ActivityManager.UID_OBSERVER_GONE,
ActivityManager.UID_OBSERVER_PROCSTATE,
ActivityManager.UID_OBSERVER_CAPABILITY,
+ ActivityManager.UID_OBSERVER_PROC_OOM_ADJ,
};
private static final int[] PROTO_ENUMS = new int[]{
ActivityManagerProto.UID_OBSERVER_FLAG_IDLE,
@@ -450,6 +465,7 @@
ActivityManagerProto.UID_OBSERVER_FLAG_GONE,
ActivityManagerProto.UID_OBSERVER_FLAG_PROCSTATE,
ActivityManagerProto.UID_OBSERVER_FLAG_CAPABILITY,
+ ActivityManagerProto.UID_OBSERVER_FLAG_PROC_OOM_ADJ,
};
UidObserverRegistration(int uid, @NonNull String pkg, int which, int cutpoint) {
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 606e6fc..5c78d1e 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -48,6 +48,9 @@
private int mSetProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
@CompositeRWLock({"mService", "mProcLock"})
+ private boolean mProcAdjChanged;
+
+ @CompositeRWLock({"mService", "mProcLock"})
private int mCurCapability;
@CompositeRWLock({"mService", "mProcLock"})
@@ -126,6 +129,7 @@
static final int CHANGE_CACHED = 1 << 3;
static final int CHANGE_UNCACHED = 1 << 4;
static final int CHANGE_CAPABILITY = 1 << 5;
+ static final int CHANGE_PROCADJ = 1 << 6;
static final int CHANGE_PROCSTATE = 1 << 31;
// Keep the enum lists in sync
@@ -186,6 +190,21 @@
mSetProcState = setProcState;
}
+ @GuardedBy({"mService", "mProcLock"})
+ void noteProcAdjChanged() {
+ mProcAdjChanged = true;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ void clearProcAdjChanged() {
+ mProcAdjChanged = false;
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ boolean getProcAdjChanged() {
+ return mProcAdjChanged;
+ }
+
@GuardedBy(anyOf = {"mService", "mProcLock"})
int getCurCapability() {
return mCurCapability;
@@ -428,6 +447,12 @@
}
sb.append("procstate");
}
+ if ((mLastReportedChange & CHANGE_PROCADJ) != 0) {
+ if (printed) {
+ sb.append("|");
+ }
+ sb.append("procadj");
+ }
}
sb.append(" procs:");
sb.append(mNumProcs);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a68fc05..dc6bd49 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -862,6 +862,9 @@
disableAudioForUid(cached, uid);
}
+ @Override public void onUidProcAdjChanged(int uid) {
+ }
+
private void disableAudioForUid(boolean disable, int uid) {
queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
disable ? 1 : 0 /* arg1 */, uid /* arg2 */,
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 589b8f1..4da8400 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1126,6 +1126,9 @@
@Override public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override public void onUidProcAdjChanged(int uid) {
+ }
};
private static final class UidStateCallbackInfo {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 25fe000..d024020 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -593,6 +593,9 @@
@Override public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override public void onUidProcAdjChanged(int uid) {
+ }
};
void handleOnUidStateChanged(int uid, int procState) {
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 8755662..dfa1281 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -256,6 +256,10 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) {
+ }
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index e9535e0..bedb9f0 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -700,5 +700,9 @@
@Override
public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override
+ public void onUidProcAdjChanged(int uid) {
+ }
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 366ab09..0e5c94f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -599,6 +599,9 @@
@Override public void onUidCachedChanged(int uid, boolean cached) {
}
+
+ @Override public void onUidProcAdjChanged(int uid) {
+ }
};
@Override