diff options
| -rw-r--r-- | services/core/java/com/android/server/AlarmManagerService.java | 26 | ||||
| -rw-r--r-- | services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java | 10 |
2 files changed, 34 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index d0edaaaf7619..b9679133b739 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -210,6 +210,7 @@ class AlarmManagerService extends SystemService { IAlarmListener mTimeTickTrigger; PendingIntent mDateChangeSender; Random mRandom; + PendingIntent.CancelListener mOperationCancelListener; boolean mInteractive = true; long mNonInteractiveStartTime; long mNonInteractiveTime; @@ -1497,6 +1498,7 @@ class AlarmManagerService extends SystemService { synchronized (mLock) { mHandler = new AlarmHandler(); + mOperationCancelListener = (intent) -> removeImpl(intent, null); mConstants = new Constants(mHandler); mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW); @@ -1748,7 +1750,9 @@ class AlarmManagerService extends SystemService { } else { maxElapsed = triggerElapsed + windowLength; } - + if (operation != null) { + operation.registerCancelListener(mOperationCancelListener); + } synchronized (mLock) { if (DEBUG_BATCH) { Slog.v(TAG, "set(" + operation + ") : type=" + type @@ -1761,6 +1765,8 @@ class AlarmManagerService extends SystemService { "Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID + " reached for uid: " + UserHandle.formatUid(callingUid) + ", callingPackage: " + callingPackage; + mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, + operation).sendToTarget(); // STOPSHIP (b/128866264): Just to catch breakages. Remove before final release. Slog.wtf(TAG, errorMsg); throw new IllegalStateException(errorMsg); @@ -1782,6 +1788,8 @@ class AlarmManagerService extends SystemService { if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) { Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a + " -- package not allowed to start"); + mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, + operation).sendToTarget(); return; } } catch (RemoteException e) { @@ -2136,10 +2144,11 @@ class AlarmManagerService extends SystemService { Slog.w(TAG, "remove() with no intent or listener"); return; } - synchronized (mLock) { removeLocked(operation, listener); } + mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, + operation).sendToTarget(); } @Override @@ -4179,6 +4188,7 @@ class AlarmManagerService extends SystemService { public static final int APP_STANDBY_BUCKET_CHANGED = 5; public static final int APP_STANDBY_PAROLE_CHANGED = 6; public static final int REMOVE_FOR_STOPPED = 7; + public static final int UNREGISTER_CANCEL_LISTENER = 8; AlarmHandler() { super(Looper.myLooper()); @@ -4261,6 +4271,13 @@ class AlarmManagerService extends SystemService { } break; + case UNREGISTER_CANCEL_LISTENER: + final PendingIntent pi = (PendingIntent) msg.obj; + if (pi != null) { + pi.unregisterCancelListener(mOperationCancelListener); + } + break; + default: // nope, just ignore it break; @@ -4716,6 +4733,11 @@ class AlarmManagerService extends SystemService { Intent.EXTRA_ALARM_COUNT, alarm.count), mDeliveryTracker, mHandler, null, allowWhileIdle ? mIdleOptions : null); + if (alarm.repeatInterval == 0) { + // Keep the listener for repeating alarms until they get cancelled + mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, + alarm.operation).sendToTarget(); + } } catch (PendingIntent.CanceledException e) { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java index cdcdf9195ad5..1e29ed6ba5f3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java @@ -1032,6 +1032,16 @@ public class AlarmManagerServiceTest { assertEquals(-1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, -1)); } + @Test + public void alarmCountOnPendingIntentCancel() { + final PendingIntent pi = getNewMockPendingIntent(); + setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 123, pi); + verify(pi).registerCancelListener(mService.mOperationCancelListener); + assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + mService.mOperationCancelListener.onCancelled(pi); + assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); + } + @After public void tearDown() { if (mMockingSession != null) { |