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

Commit 5bfaaa61 authored by Suprabh Shukla's avatar Suprabh Shukla
Browse files

Remove listener alarms when remote binder dies

Listener alarms without a live binder would unfairly count towards the
quota of the scheduling package.

Test: atest FrameworksMockingServicesTests:\
com.android.server.AlarmManagerServiceTest

Bug: 135633339
Change-Id: Iea76f312ef9512a4463204044cbae2593e43634e
parent b8f20004
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -208,6 +208,7 @@ class AlarmManagerService extends SystemService {
    AppWakeupHistory mAppWakeupHistory;
    ClockReceiver mClockReceiver;
    final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
    IBinder.DeathRecipient mListenerDeathRecipient;
    Intent mTimeTickIntent;
    IAlarmListener mTimeTickTrigger;
    PendingIntent mDateChangeSender;
@@ -1447,6 +1448,18 @@ class AlarmManagerService extends SystemService {
    public void onStart() {
        mInjector.init();

        mListenerDeathRecipient = new IBinder.DeathRecipient() {
            @Override
            public void binderDied() {
            }

            @Override
            public void binderDied(IBinder who) {
                final IAlarmListener listener = IAlarmListener.Stub.asInterface(who);
                removeImpl(null, listener);
            }
        };

        synchronized (mLock) {
            mHandler = new AlarmHandler();
            mConstants = new Constants(mHandler);
@@ -1653,6 +1666,15 @@ class AlarmManagerService extends SystemService {
            return;
        }

        if (directReceiver != null) {
            try {
                directReceiver.asBinder().linkToDeath(mListenerDeathRecipient, 0);
            } catch (RemoteException e) {
                Slog.w(TAG, "Dropping unreachable alarm listener " + listenerTag);
                return;
            }
        }

        // Sanity check the window length.  This will catch people mistakenly
        // trying to pass an end-of-window timestamp rather than a duration.
        if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
+21 −2
Original line number Diff line number Diff line
@@ -345,8 +345,8 @@ public class AlarmManagerServiceTest {
    }

    /**
     * Lowers quotas to make testing feasible.
     * Careful while calling as this will replace any existing settings for the calling test.
     * Lowers quotas to make testing feasible. Careful while calling as this will replace any
     * existing settings for the calling test.
     */
    private void setTestableQuotas() {
        final StringBuilder constantsBuilder = new StringBuilder();
@@ -981,6 +981,25 @@ public class AlarmManagerServiceTest {
        assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
    }

    @Test
    public void alarmCountOnListenerBinderDied() {
        final int numAlarms = 10;
        final IAlarmListener[] listeners = new IAlarmListener[numAlarms];
        for (int i = 0; i < numAlarms; i++) {
            listeners[i] = new IAlarmListener.Stub() {
                @Override
                public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
                }
            };
            setTestAlarmWithListener(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + i, listeners[i]);
        }
        assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
        for (int i = 0; i < numAlarms; i++) {
            mService.mListenerDeathRecipient.binderDied(listeners[i].asBinder());
            assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
        }
    }

    @After
    public void tearDown() {
        if (mMockingSession != null) {