Preserve enqueue time of replaced broadcast records.
When a broadcast is sent with FLAG_RECEIVER_REPLACE_PENDING, we perform in-place swap with older broadcasts but we don't update the enqueue times and this could result in other processes getting prioritized even though they have broadcasts that have been enqueued at a later time. Bug: 263803500 Test: atest services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java Test: atest services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java Change-Id: Ie4524a6b05d66be0725650be888f45d2903e1daa
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<String> componentNameList) {
|
||||
final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
|
||||
packageChangedIntent.putExtra(Intent.EXTRA_UID, uid);
|
||||
|
||||
Reference in New Issue
Block a user