diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bfa397fa2b036..ca4a253e779c4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17236,6 +17236,12 @@ public class ActivityManagerService extends IActivityManager.Stub } } + void onProcessFreezableChangedLocked(ProcessRecord app) { + if (mEnableModernQueue) { + mBroadcastQueues[0].onProcessFreezableChangedLocked(app); + } + } + @VisibleForTesting public final class LocalService extends ActivityManagerInternal implements ActivityManagerLocal { diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index 3ac2b2bd9fd1b..142a5dc6db0fb 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -201,7 +201,7 @@ class BroadcastProcessQueue { private boolean mLastDeferredStates; private boolean mUidForeground; - private boolean mUidCached; + private boolean mProcessFreezable; private boolean mProcessInstrumented; private boolean mProcessPersistent; @@ -411,7 +411,7 @@ class BroadcastProcessQueue { */ @CheckResult public boolean setProcessAndUidState(@Nullable ProcessRecord app, boolean uidForeground, - boolean uidCached) { + boolean processFreezable) { this.app = app; // Since we may have just changed our PID, invalidate cached strings @@ -420,13 +420,13 @@ class BroadcastProcessQueue { boolean didSomething = false; if (app != null) { - didSomething |= setUidCached(uidCached); didSomething |= setUidForeground(uidForeground); + didSomething |= setProcessFreezable(processFreezable); didSomething |= setProcessInstrumented(app.getActiveInstrumentation() != null); didSomething |= setProcessPersistent(app.isPersistent()); } else { - didSomething |= setUidCached(uidCached); didSomething |= setUidForeground(false); + didSomething |= setProcessFreezable(false); didSomething |= setProcessInstrumented(false); didSomething |= setProcessPersistent(false); } @@ -450,13 +450,13 @@ class BroadcastProcessQueue { } /** - * Update if this process is in the "cached" state, typically signaling that + * Update if this process is in the "freezable" state, typically signaling that * broadcast dispatch should be paused or delayed. */ @CheckResult - private boolean setUidCached(boolean uidCached) { - if (mUidCached != uidCached) { - mUidCached = uidCached; + private boolean setProcessFreezable(boolean freezable) { + if (mProcessFreezable != freezable) { + mProcessFreezable = freezable; invalidateRunnableAt(); return true; } else { @@ -1115,7 +1115,7 @@ class BroadcastProcessQueue { } else if (mCountManifest > 0) { mRunnableAt = runnableAt; mRunnableAtReason = REASON_CONTAINS_MANIFEST; - } else if (mUidCached) { + } else if (mProcessFreezable) { if (r.deferUntilActive) { // All enqueued broadcasts are deferrable, defer if (mCountDeferred == mCountEnqueued) { @@ -1185,7 +1185,7 @@ class BroadcastProcessQueue { // When all we have pending is deferred broadcasts, and we're cached, // then we want everything to be marked deferred final boolean wantDeferredStates = (mCountDeferred > 0) - && (mCountDeferred == mCountEnqueued) && mUidCached; + && (mCountDeferred == mCountEnqueued) && mProcessFreezable; if (mLastDeferredStates != wantDeferredStates) { mLastDeferredStates = wantDeferredStates; @@ -1372,9 +1372,9 @@ class BroadcastProcessQueue { if (mUidForeground) { sb.append("FG"); } - if (mUidCached) { + if (mProcessFreezable) { if (sb.length() > 0) sb.append("|"); - sb.append("CACHED"); + sb.append("FRZN"); } if (mProcessInstrumented) { if (sb.length() > 0) sb.append("|"); diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 8e76e5b5cf484..93bde6f1132ba 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -172,6 +172,13 @@ public abstract class BroadcastQueue { @GuardedBy("mService") public abstract void onApplicationCleanupLocked(@NonNull ProcessRecord app); + /** + * Signal from OS internals that the given process is in a freezable state and will be + * freezed soon after. + */ + @GuardedBy("mService") + public abstract void onProcessFreezableChangedLocked(@NonNull ProcessRecord app); + /** * Signal from OS internals that the given package (or some subset of that * package) has been disabled or uninstalled, and that any pending diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java index 7f3ceb578891f..ce635f1076c11 100644 --- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java +++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java @@ -449,6 +449,10 @@ public class BroadcastQueueImpl extends BroadcastQueue { skipCurrentOrPendingReceiverLocked(app); } + public void onProcessFreezableChangedLocked(ProcessRecord app) { + // Not supported; ignore + } + public boolean sendPendingBroadcastsLocked(ProcessRecord app) { boolean didSomething = false; final BroadcastRecord br = mPendingBroadcast; diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java index d6e692cfdc009..331efaa35c5c4 100644 --- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java @@ -223,16 +223,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue { @GuardedBy("mService") private final SparseBooleanArray mUidForeground = new SparseBooleanArray(); - /** - * Map from UID to its last known "cached" state. - *
- * We manually maintain this data structure since the lifecycle of
- * {@link ProcessRecord} and {@link BroadcastProcessQueue} can be
- * mismatched.
- */
- @GuardedBy("mService")
- private final SparseBooleanArray mUidCached = new SparseBooleanArray();
-
private final BroadcastConstants mConstants;
private final BroadcastConstants mFgConstants;
private final BroadcastConstants mBgConstants;
@@ -574,6 +564,13 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
}
}
+ @Override
+ public void onProcessFreezableChangedLocked(@NonNull ProcessRecord app) {
+ synchronized (mService) {
+ refreshProcessQueueLocked(app);
+ }
+ }
+
@Override
public int getPreferredSchedulingGroupLocked(@NonNull ProcessRecord app) {
final BroadcastProcessQueue queue = getProcessQueue(app);
@@ -1305,7 +1302,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
};
broadcastPredicate = BROADCAST_PREDICATE_ANY;
- cleanupUserStateLocked(mUidCached, userId);
cleanupUserStateLocked(mUidForeground, userId);
}
return forEachMatchingBroadcast(queuePredicate, broadcastPredicate,
@@ -1448,20 +1444,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
refreshProcessQueuesLocked(uid);
}
}
-
- @Override
- public void onUidCachedChanged(int uid, boolean cached) {
- synchronized (mService) {
- if (cached) {
- mUidCached.put(uid, true);
- } else {
- mUidCached.delete(uid);
- }
- refreshProcessQueuesLocked(uid);
- }
- }
- }, ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_CACHED,
- ActivityManager.PROCESS_STATE_TOP, "android");
+ }, ActivityManager.UID_OBSERVER_PROCSTATE, ActivityManager.PROCESS_STATE_TOP, "android");
// Kick off periodic health checks
mLocalHandler.sendEmptyMessage(MSG_CHECK_HEALTH);
@@ -1650,10 +1633,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// warm via this operation, we're going to immediately promote it to
// be running, and any side effect of this operation will then apply
// after it's finished and is returned to the runnable list.
- queue.setProcessAndUidState(
- mService.getProcessRecordLocked(queue.processName, queue.uid),
- mUidForeground.get(queue.uid, false),
- mUidCached.get(queue.uid, false));
+ final ProcessRecord app = mService.getProcessRecordLocked(queue.processName, queue.uid);
+ queue.setProcessAndUidState(app, mUidForeground.get(queue.uid, false),
+ isProcessFreezable(app));
}
}
@@ -1665,11 +1647,21 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
private void setQueueProcess(@NonNull BroadcastProcessQueue queue,
@Nullable ProcessRecord app) {
if (queue.setProcessAndUidState(app, mUidForeground.get(queue.uid, false),
- mUidCached.get(queue.uid, false))) {
+ isProcessFreezable(app))) {
updateRunnableList(queue);
}
}
+ @GuardedBy("mService")
+ private boolean isProcessFreezable(@Nullable ProcessRecord app) {
+ if (app == null) {
+ return false;
+ }
+ synchronized (mService.mProcLock) {
+ return app.mOptRecord.isPendingFreeze() || app.mOptRecord.isFrozen();
+ }
+ }
+
/**
* Refresh the process queues with the latest process state so that runnableAt
* can be updated.
@@ -1686,6 +1678,20 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
enqueueUpdateRunningList();
}
+ /**
+ * Refresh the process queue corresponding to {@code app} with the latest process state
+ * so that runnableAt can be updated.
+ */
+ @GuardedBy("mService")
+ private void refreshProcessQueueLocked(@NonNull ProcessRecord app) {
+ final BroadcastProcessQueue queue = getProcessQueue(app.processName, app.uid);
+ if (queue == null || queue.app == null || queue.app.getPid() != app.getPid()) {
+ return;
+ }
+ setQueueProcess(queue, queue.app);
+ enqueueUpdateRunningList();
+ }
+
/**
* Inform other parts of OS that the given broadcast queue has started
* running, typically for internal bookkeeping.
@@ -2005,12 +2011,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
ipw.decreaseIndent();
ipw.println();
- ipw.println("Cached UIDs:");
- ipw.increaseIndent();
- ipw.println(mUidCached);
- ipw.decreaseIndent();
- ipw.println();
-
ipw.println("Foreground UIDs:");
ipw.increaseIndent();
ipw.println(mUidForeground);
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 7773190d22b6e..e5a175917f34c 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -300,6 +300,7 @@ public final class CachedAppOptimizer {
static final int COMPACT_NATIVE_MSG = 5;
static final int UID_FROZEN_STATE_CHANGED_MSG = 6;
static final int DEADLOCK_WATCHDOG_MSG = 7;
+ static final int REPORT_PROCESS_FREEZABLE_CHANGED = 8;
// When free swap falls below this percentage threshold any full (file + anon)
// compactions will be downgraded to file only compactions to reduce pressure
@@ -1352,6 +1353,7 @@ public final class CachedAppOptimizer {
}
}
}
+ postProcessFreezableChangedMessage(app);
mFreezeHandler.sendMessageDelayed(
mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),
delayMillis);
@@ -1389,6 +1391,7 @@ public final class CachedAppOptimizer {
uidRec.setFrozen(false);
postUidFrozenMessage(uidRec.getUid(), false);
}
+ postProcessFreezableChangedMessage(app);
opt.setFreezerOverride(false);
if (pid == 0 || !opt.isFrozen()) {
@@ -2066,6 +2069,21 @@ public final class CachedAppOptimizer {
0, uidObj));
}
+ private void reportProcessFreezableChanged(ProcessRecord app) {
+ synchronized (mAm) {
+ mAm.onProcessFreezableChangedLocked(app);
+ }
+ }
+
+ @GuardedBy("mAm")
+ private void postProcessFreezableChangedMessage(ProcessRecord app) {
+ if (app.getPid() == 0) {
+ return;
+ }
+ mFreezeHandler.obtainMessage(REPORT_PROCESS_FREEZABLE_CHANGED, 0, 0, app)
+ .sendToTarget();
+ }
+
private final class FreezeHandler extends Handler implements
ProcLocksReader.ProcLocksReaderCallback {
private FreezeHandler() {
@@ -2075,7 +2093,7 @@ public final class CachedAppOptimizer {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case SET_FROZEN_PROCESS_MSG:
+ case SET_FROZEN_PROCESS_MSG: {
ProcessRecord proc = (ProcessRecord) msg.obj;
synchronized (mAm) {
freezeProcess(proc);
@@ -2085,8 +2103,8 @@ public final class CachedAppOptimizer {
removeMessages(DEADLOCK_WATCHDOG_MSG);
sendEmptyMessageDelayed(DEADLOCK_WATCHDOG_MSG, FREEZE_DEADLOCK_TIMEOUT_MS);
}
- break;
- case REPORT_UNFREEZE_MSG:
+ } break;
+ case REPORT_UNFREEZE_MSG: {
int pid = msg.arg1;
int frozenDuration = msg.arg2;
Pair