summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java26
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java10
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) {