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

Commit f5a222bf authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Acquire wakelock before alarm dispatch" into main

parents 01249642 6714f64f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -7,3 +7,13 @@ flag {
    description: "Persist list of users with alarms scheduled and wakeup stopped users before alarms are due"
    bug: "314907186"
}

flag {
    name: "acquire_wakelock_before_send"
    namespace: "backstage_power"
    description: "Acquire the userspace alarm wakelock before sending the alarm"
    bug: "391413964"
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}
+19 −5
Original line number Diff line number Diff line
@@ -5334,6 +5334,18 @@ public class AlarmManagerService extends SystemService {
        public void deliverLocked(Alarm alarm, long nowELAPSED) {
            final long workSourceToken = ThreadLocalWorkSource.setUid(
                    getAlarmAttributionUid(alarm));

            if (Flags.acquireWakelockBeforeSend()) {
                // Acquire the wakelock before starting the app. This needs to be done to avoid
                // random stalls in the receiving app in case a suspend attempt is already in
                // progress. See b/391413964 for an incident where this was found to happen.
                if (mBroadcastRefCount == 0) {
                    setWakelockWorkSource(alarm.workSource, alarm.creatorUid, alarm.statsTag, true);
                    mWakeLock.acquire();
                    mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1, 0).sendToTarget();
                }
            }

            try {
                if (alarm.operation != null) {
                    // PendingIntent alarm
@@ -5399,15 +5411,17 @@ public class AlarmManagerService extends SystemService {
                ThreadLocalWorkSource.restore(workSourceToken);
            }

            // The alarm is now in flight; now arrange wakelock and stats tracking
            if (DEBUG_WAKELOCK) {
                Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
            }
            if (!Flags.acquireWakelockBeforeSend()) {
                // The alarm is now in flight; now arrange wakelock and stats tracking
                if (mBroadcastRefCount == 0) {
                    setWakelockWorkSource(alarm.workSource, alarm.creatorUid, alarm.statsTag, true);
                    mWakeLock.acquire();
                    mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1, 0).sendToTarget();
                }
            }
            final InFlight inflight = new InFlight(AlarmManagerService.this, alarm, nowELAPSED);
            mInFlight.add(inflight);
            mBroadcastRefCount++;
+26 −0
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.flag.util.FlagSetException;
@@ -192,7 +193,9 @@ import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;

@@ -435,6 +438,7 @@ public final class AlarmManagerServiceTest {
    private void disableFlagsNotSetByAnnotation() {
        try {
            mSetFlagsRule.disableFlags(Flags.FLAG_START_USER_BEFORE_SCHEDULED_ALARMS);
            mSetFlagsRule.disableFlags(Flags.FLAG_ACQUIRE_WAKELOCK_BEFORE_SEND);
        } catch (FlagSetException fse) {
            // Expected if the test about to be run requires this enabled.
        }
@@ -947,6 +951,28 @@ public final class AlarmManagerServiceTest {
        assertEquals(expectedTriggerTime, mTestTimer.getElapsed());
    }

    @Test
    @EnableFlags(Flags.FLAG_ACQUIRE_WAKELOCK_BEFORE_SEND)
    public void testWakelockOrdering() throws Exception {
        final long triggerTime = mNowElapsedTest + 5000;
        final PendingIntent alarmPi = getNewMockPendingIntent();
        setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi);

        mNowElapsedTest = mTestTimer.getElapsed();
        mTestTimer.expire();

        final InOrder inOrder = Mockito.inOrder(alarmPi, mWakeLock);
        inOrder.verify(mWakeLock).acquire();

        final ArgumentCaptor<PendingIntent.OnFinished> onFinishedCaptor =
                ArgumentCaptor.forClass(PendingIntent.OnFinished.class);
        inOrder.verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class),
                onFinishedCaptor.capture(), any(Handler.class), isNull(), any());
        onFinishedCaptor.getValue().onSendFinished(alarmPi, null, 0, null, null);

        inOrder.verify(mWakeLock).release();
    }

    @Test
    public void testMinFuturityCoreUid() {
        setDeviceConfigLong(KEY_MIN_FUTURITY, 10L);