Merge "Adding an API to cancel all alarms"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f24bb33b6e
@@ -1256,6 +1256,17 @@ public class AlarmManager {
|
||||
wrapper.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all alarms previously set by the caller, if any.
|
||||
*/
|
||||
public void cancelAll() {
|
||||
try {
|
||||
mService.removeAll(mContext.getOpPackageName());
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the system wall clock time.
|
||||
* Requires the permission android.permission.SET_TIME.
|
||||
|
||||
@@ -37,6 +37,7 @@ interface IAlarmManager {
|
||||
boolean setTime(long millis);
|
||||
void setTimeZone(String zone);
|
||||
void remove(in PendingIntent operation, in IAlarmListener listener);
|
||||
void removeAll(String packageName);
|
||||
long getNextWakeFromIdleTime();
|
||||
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
|
||||
AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
|
||||
|
||||
@@ -2969,6 +2969,24 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll(String callingPackage) {
|
||||
final int callingUid = mInjector.getCallingUid();
|
||||
if (callingUid == Process.SYSTEM_UID) {
|
||||
Slog.wtfStack(TAG, "Attempt to remove all alarms from the system uid package: "
|
||||
+ callingPackage);
|
||||
return;
|
||||
}
|
||||
if (callingUid != mPackageManagerInternal.getPackageUid(callingPackage, 0,
|
||||
UserHandle.getUserId(callingUid))) {
|
||||
throw new SecurityException("Package " + callingPackage
|
||||
+ " does not belong to the calling uid " + callingUid);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
removeLocked(callingPackage, REMOVE_REASON_ALARM_CANCELLED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNextWakeFromIdleTime() {
|
||||
return getNextWakeFromIdleTimeImpl();
|
||||
@@ -4081,7 +4099,7 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void removeLocked(final String packageName) {
|
||||
void removeLocked(final String packageName, int reason) {
|
||||
if (packageName == null) {
|
||||
if (localLOGV) {
|
||||
Slog.w(TAG, "requested remove() of null packageName",
|
||||
@@ -4089,7 +4107,7 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
return;
|
||||
}
|
||||
removeAlarmsInternalLocked(a -> a.matches(packageName), REMOVE_REASON_UNDEFINED);
|
||||
removeAlarmsInternalLocked(a -> a.matches(packageName), reason);
|
||||
}
|
||||
|
||||
// Only called for ephemeral apps
|
||||
@@ -5132,7 +5150,7 @@ public class AlarmManagerService extends SystemService {
|
||||
removeLocked(uid, REMOVE_REASON_UNDEFINED);
|
||||
} else {
|
||||
// external-applications-unavailable case
|
||||
removeLocked(pkg);
|
||||
removeLocked(pkg, REMOVE_REASON_UNDEFINED);
|
||||
}
|
||||
mPriorities.remove(pkg);
|
||||
for (int i = mBroadcastStats.size() - 1; i >= 0; i--) {
|
||||
|
||||
@@ -4596,6 +4596,7 @@ package android.app {
|
||||
method public boolean canScheduleExactAlarms();
|
||||
method public void cancel(android.app.PendingIntent);
|
||||
method public void cancel(android.app.AlarmManager.OnAlarmListener);
|
||||
method public void cancelAll();
|
||||
method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock();
|
||||
method public void set(int, long, android.app.PendingIntent);
|
||||
method public void set(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler);
|
||||
|
||||
@@ -254,6 +254,7 @@ public class AlarmManagerServiceTest {
|
||||
private Injector mInjector;
|
||||
private volatile long mNowElapsedTest;
|
||||
private volatile long mNowRtcTest;
|
||||
private volatile int mTestCallingUid = TEST_CALLING_UID;
|
||||
@GuardedBy("mTestTimer")
|
||||
private TestTimer mTestTimer = new TestTimer();
|
||||
|
||||
@@ -328,7 +329,7 @@ public class AlarmManagerServiceTest {
|
||||
|
||||
@Override
|
||||
int getCallingUid() {
|
||||
return TEST_CALLING_UID;
|
||||
return mTestCallingUid;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1395,7 +1396,7 @@ public class AlarmManagerServiceTest {
|
||||
setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent());
|
||||
}
|
||||
assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
|
||||
mService.removeLocked(TEST_CALLING_PACKAGE);
|
||||
mService.removeLocked(TEST_CALLING_PACKAGE, REMOVE_REASON_UNDEFINED);
|
||||
assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
|
||||
}
|
||||
|
||||
@@ -2682,6 +2683,59 @@ public class AlarmManagerServiceTest {
|
||||
eq(EXACT_ALLOW_REASON_ALLOW_LIST));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAllBinderCall() throws RemoteException {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 1, getNewMockPendingIntent());
|
||||
}
|
||||
|
||||
final String otherUidPackage1 = "other.uid.package1";
|
||||
final String otherUidPackage2 = "other.uid.package2";
|
||||
final int otherUid = 1243;
|
||||
|
||||
registerAppIds(
|
||||
new String[]{TEST_CALLING_PACKAGE, otherUidPackage1, otherUidPackage2},
|
||||
new Integer[]{TEST_CALLING_UID, otherUid, otherUid}
|
||||
);
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 11, 0,
|
||||
getNewMockPendingIntent(otherUid, otherUidPackage1), 0, 0, otherUid,
|
||||
otherUidPackage1, null);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 20, 0,
|
||||
getNewMockPendingIntent(otherUid, otherUidPackage2), 0, 0, otherUid,
|
||||
otherUidPackage2, null);
|
||||
}
|
||||
|
||||
assertEquals(27, mService.mAlarmStore.size());
|
||||
|
||||
try {
|
||||
mBinder.removeAll(otherUidPackage1);
|
||||
fail("removeAll() for wrong package did not throw SecurityException");
|
||||
} catch (SecurityException se) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
try {
|
||||
mBinder.removeAll(otherUidPackage2);
|
||||
fail("removeAll() for wrong package did not throw SecurityException");
|
||||
} catch (SecurityException se) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
mBinder.removeAll(TEST_CALLING_PACKAGE);
|
||||
assertEquals(17, mService.mAlarmStore.size());
|
||||
assertEquals(0, mService.mAlarmStore.getCount(a -> a.matches(TEST_CALLING_PACKAGE)));
|
||||
|
||||
mTestCallingUid = otherUid;
|
||||
mBinder.removeAll(otherUidPackage1);
|
||||
assertEquals(0, mService.mAlarmStore.getCount(a -> a.matches(otherUidPackage1)));
|
||||
assertEquals(8, mService.mAlarmStore.getCount(a -> a.matches(otherUidPackage2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minWindowChangeEnabled() {
|
||||
mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true);
|
||||
@@ -3577,7 +3631,7 @@ public class AlarmManagerServiceTest {
|
||||
getNewMockPendingIntent()), standbyQuota + temporaryQuota, mAppStandbyWindow);
|
||||
|
||||
// refresh the state.
|
||||
mService.removeLocked(TEST_CALLING_PACKAGE);
|
||||
mService.removeLocked(TEST_CALLING_PACKAGE, REMOVE_REASON_UNDEFINED);
|
||||
mService.mAppWakeupHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
|
||||
mService.mTemporaryQuotaReserve.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
|
||||
|
||||
@@ -3586,7 +3640,7 @@ public class AlarmManagerServiceTest {
|
||||
getNewMockPendingIntent()), standbyQuota + temporaryQuota, mAppStandbyWindow);
|
||||
|
||||
// refresh the state.
|
||||
mService.removeLocked(TEST_CALLING_PACKAGE);
|
||||
mService.removeLocked(TEST_CALLING_PACKAGE, REMOVE_REASON_UNDEFINED);
|
||||
mService.mAppWakeupHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
|
||||
mService.mTemporaryQuotaReserve.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user