diff options
3 files changed, 42 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index 58f62b67ae11..0fcec6faa0cc 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -25,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UptimeMillisLong; +import android.app.ActivityManager; import android.app.BroadcastOptions; import android.content.Intent; import android.content.pm.ResolveInfo; @@ -1045,6 +1046,7 @@ class BroadcastProcessQueue { static final int REASON_CONTAINS_MANIFEST = 17; static final int REASON_FOREGROUND = 18; static final int REASON_CORE_UID = 19; + static final int REASON_TOP_PROCESS = 20; @IntDef(flag = false, prefix = { "REASON_" }, value = { REASON_EMPTY, @@ -1066,6 +1068,7 @@ class BroadcastProcessQueue { REASON_CONTAINS_MANIFEST, REASON_FOREGROUND, REASON_CORE_UID, + REASON_TOP_PROCESS, }) @Retention(RetentionPolicy.SOURCE) public @interface Reason {} @@ -1091,6 +1094,7 @@ class BroadcastProcessQueue { case REASON_CONTAINS_MANIFEST: return "CONTAINS_MANIFEST"; case REASON_FOREGROUND: return "FOREGROUND"; case REASON_CORE_UID: return "CORE_UID"; + case REASON_TOP_PROCESS: return "TOP_PROCESS"; default: return Integer.toString(reason); } } @@ -1132,6 +1136,11 @@ class BroadcastProcessQueue { } else if (mUidForeground) { mRunnableAt = runnableAt + constants.DELAY_FOREGROUND_PROC_MILLIS; mRunnableAtReason = REASON_FOREGROUND; + } else if (app != null && app.getSetProcState() == ActivityManager.PROCESS_STATE_TOP) { + // TODO (b/287676625): Use a callback to check when a process goes in and out of + // the TOP state. + mRunnableAt = runnableAt + constants.DELAY_FOREGROUND_PROC_MILLIS; + mRunnableAtReason = REASON_TOP_PROCESS; } else if (mProcessPersistent) { mRunnableAt = runnableAt + constants.DELAY_PERSISTENT_PROC_MILLIS; mRunnableAtReason = REASON_PERSISTENT; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index f814c3b3112d..f532122c10d9 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -674,6 +674,11 @@ class ProcessRecord implements WindowProcessListener { return mState.getCurProcState(); } + @GuardedBy(anyOf = {"mService", "mProcLock"}) + int getSetProcState() { + return mState.getSetProcState(); + } + @GuardedBy({"mService", "mProcLock"}) public void makeActive(IApplicationThread thread, ProcessStatsService tracker) { mProfile.onProcessActive(thread, tracker); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java index 3b3e7cdb496c..6bcc14e97955 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java @@ -66,6 +66,7 @@ import static org.mockito.Mockito.times; import android.annotation.NonNull; import android.app.Activity; +import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.BackgroundStartPrivileges; import android.app.BroadcastOptions; @@ -555,6 +556,33 @@ public final class BroadcastQueueModernImplTest { } @Test + public void testRunnableAt_processTop() { + final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, + getUidForPackage(PACKAGE_GREEN)); + + doReturn(ActivityManager.PROCESS_STATE_TOP).when(mProcess).getSetProcState(); + queue.setProcessAndUidState(mProcess, false, false); + + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, + List.of(makeMockRegisteredReceiver())); + enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); + + assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); + assertEquals(BroadcastProcessQueue.REASON_TOP_PROCESS, queue.getRunnableAtReason()); + + doReturn(ActivityManager.PROCESS_STATE_SERVICE).when(mProcess).getSetProcState(); + queue.setProcessAndUidState(mProcess, false, false); + + // The new process state will only be taken into account the next time a broadcast + // is sent to the process. + enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(timeTick, + List.of(makeMockRegisteredReceiver())), 0); + assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + } + + @Test public void testRunnableAt_persistentProc() { final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); |