Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13b8910d authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

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
parent 09183fb1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;
+17 −1
Original line number Diff line number Diff line
@@ -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;
    }
+29 −0
Original line number Diff line number Diff line
@@ -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);