diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index d53f8fb1c8822..bec2a2e5f53a0 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -266,6 +266,7 @@ class BroadcastProcessQueue { // Exact match found; perform in-place swap args.arg1 = record; args.argi1 = recordIndex; + record.copyEnqueueTimeFrom(testRecord); onBroadcastDequeued(testRecord, testRecordIndex); onBroadcastEnqueued(record, recordIndex); return true; diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index 24cf3d2800638..9f31f64a5c26d 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -106,6 +106,10 @@ final class BroadcastRecord extends Binder { @UptimeMillisLong long enqueueTime; // when broadcast enqueued @ElapsedRealtimeLong long enqueueRealTime; // when broadcast enqueued @CurrentTimeMillisLong long enqueueClockTime; // when broadcast enqueued + // When broadcast is originally enqueued. Only used in case of replacing broadcasts + // with FLAG_RECEIVER_REPLACE_PENDING. If it is 0, then 'enqueueClockTime' is the original + // enqueue time. + @UptimeMillisLong long originalEnqueueClockTime; @UptimeMillisLong long dispatchTime; // when broadcast dispatch started @ElapsedRealtimeLong long dispatchRealTime; // when broadcast dispatch started @CurrentTimeMillisLong long dispatchClockTime; // when broadcast dispatch started @@ -252,7 +256,12 @@ final class BroadcastRecord extends Binder { pw.print(prefix); pw.print("enqueueClockTime="); pw.print(sdf.format(new Date(enqueueClockTime))); pw.print(" dispatchClockTime="); - pw.println(sdf.format(new Date(dispatchClockTime))); + pw.print(sdf.format(new Date(dispatchClockTime))); + if (originalEnqueueClockTime > 0) { + pw.print(" originalEnqueueClockTime="); + pw.print(sdf.format(new Date(originalEnqueueClockTime))); + } + pw.println(); pw.print(prefix); pw.print("dispatchTime="); TimeUtils.formatDuration(dispatchTime, now, pw); pw.print(" ("); @@ -615,6 +624,13 @@ final class BroadcastRecord extends Binder { return delivery[index]; } + void copyEnqueueTimeFrom(@NonNull BroadcastRecord replacedBroadcast) { + originalEnqueueClockTime = enqueueClockTime; + enqueueTime = replacedBroadcast.enqueueTime; + enqueueRealTime = replacedBroadcast.enqueueRealTime; + enqueueClockTime = replacedBroadcast.enqueueClockTime; + } + boolean isForeground() { return (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0; } 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 8d78cd6fb0124..60f86219e6ab3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java @@ -946,6 +946,35 @@ public class BroadcastQueueModernImplTest { List.of(musicVolumeChanged, alarmVolumeChanged, timeTick)); } + @Test + public void testVerifyEnqueuedTime_withReplacePending() { + final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT); + userPresent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + + // Halt all processing so that we get a consistent view + mHandlerThread.getLooper().getQueue().postSyncBarrier(); + + final BroadcastRecord userPresentRecord1 = makeBroadcastRecord(userPresent); + final BroadcastRecord userPresentRecord2 = makeBroadcastRecord(userPresent); + + mImpl.enqueueBroadcastLocked(userPresentRecord1); + mImpl.enqueueBroadcastLocked(userPresentRecord2); + + final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN, + getUidForPackage(PACKAGE_GREEN)); + queue.makeActiveNextPending(); + + // Verify that there is only one record pending and its enqueueTime is + // same as that of userPresentRecord1. + final BroadcastRecord activeRecord = queue.getActive(); + assertEquals(userPresentRecord1.enqueueTime, activeRecord.enqueueTime); + assertEquals(userPresentRecord1.enqueueRealTime, activeRecord.enqueueRealTime); + assertEquals(userPresentRecord1.enqueueClockTime, activeRecord.enqueueClockTime); + assertThat(activeRecord.originalEnqueueClockTime) + .isGreaterThan(activeRecord.enqueueClockTime); + assertTrue(queue.isEmpty()); + } + private Intent createPackageChangedIntent(int uid, List componentNameList) { final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED); packageChangedIntent.putExtra(Intent.EXTRA_UID, uid);