Merge "Exempting prioritized alarms from min_window" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9863f6343b
@@ -1684,17 +1684,13 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
|
||||
// Do not support windows for idle-until alarms.
|
||||
windowLength = AlarmManager.WINDOW_EXACT;
|
||||
}
|
||||
|
||||
// Snap the window to reasonable limits.
|
||||
if (windowLength > INTERVAL_DAY) {
|
||||
Slog.w(TAG, "Window length " + windowLength
|
||||
+ "ms suspiciously long; limiting to 1 day");
|
||||
windowLength = INTERVAL_DAY;
|
||||
} else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW) {
|
||||
} else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW
|
||||
&& (flags & FLAG_PRIORITIZE) == 0) {
|
||||
if (CompatChanges.isChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS,
|
||||
callingPackage, UserHandle.getUserHandleForUid(callingUid))) {
|
||||
Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to "
|
||||
@@ -1741,7 +1737,7 @@ public class AlarmManagerService extends SystemService {
|
||||
final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
|
||||
|
||||
final long maxElapsed;
|
||||
if (windowLength == AlarmManager.WINDOW_EXACT) {
|
||||
if (windowLength == 0) {
|
||||
maxElapsed = triggerElapsed;
|
||||
} else if (windowLength < 0) {
|
||||
maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
|
||||
@@ -2145,17 +2141,63 @@ public class AlarmManagerService extends SystemService {
|
||||
+ " does not belong to the calling uid " + callingUid);
|
||||
}
|
||||
|
||||
final boolean allowWhileIdle = (flags & FLAG_ALLOW_WHILE_IDLE) != 0;
|
||||
final boolean exact = (windowLength == AlarmManager.WINDOW_EXACT);
|
||||
// Repeating alarms must use PendingIntent, not direct listener
|
||||
if (interval != 0 && directReceiver != null) {
|
||||
throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
|
||||
}
|
||||
|
||||
// make sure the caller is allowed to use the requested kind of alarm, and also
|
||||
if (workSource != null) {
|
||||
getContext().enforcePermission(
|
||||
android.Manifest.permission.UPDATE_DEVICE_STATS,
|
||||
Binder.getCallingPid(), callingUid, "AlarmManager.set");
|
||||
}
|
||||
|
||||
if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
|
||||
// Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
|
||||
// manager when to come out of idle mode, which is only for DeviceIdleController.
|
||||
if (callingUid != Process.SYSTEM_UID) {
|
||||
// TODO (b/169463012): Throw instead of tolerating this mistake.
|
||||
flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
|
||||
} else {
|
||||
// Do not support windows for idle-until alarms.
|
||||
windowLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove flags reserved for the service, we will apply those later as appropriate.
|
||||
flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
|
||||
| FLAG_ALLOW_WHILE_IDLE_COMPAT);
|
||||
|
||||
// If this alarm is for an alarm clock, then it must be exact and we will
|
||||
// use it to wake early from idle if needed.
|
||||
if (alarmClock != null) {
|
||||
flags |= FLAG_WAKE_FROM_IDLE;
|
||||
windowLength = 0;
|
||||
|
||||
// If the caller is a core system component or on the user's allowlist, and not calling
|
||||
// to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
|
||||
// This means we will allow these alarms to go off as normal even while idle, with no
|
||||
// timing restrictions.
|
||||
} else if (workSource == null && (UserHandle.isCore(callingUid)
|
||||
|| UserHandle.isSameApp(callingUid, mSystemUiUid)
|
||||
|| ((mAppStateTracker != null)
|
||||
&& mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) {
|
||||
flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
|
||||
flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_PRIORITIZE);
|
||||
}
|
||||
|
||||
final boolean allowWhileIdle = (flags & FLAG_ALLOW_WHILE_IDLE) != 0;
|
||||
final boolean exact = (windowLength == 0);
|
||||
|
||||
// Make sure the caller is allowed to use the requested kind of alarm, and also
|
||||
// decide what quota and broadcast options to use.
|
||||
Bundle idleOptions = null;
|
||||
if ((flags & FLAG_PRIORITIZE) != 0) {
|
||||
getContext().enforcePermission(
|
||||
Manifest.permission.SCHEDULE_PRIORITIZED_ALARM,
|
||||
Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized");
|
||||
flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_ALLOW_WHILE_IDLE_COMPAT);
|
||||
// The API doesn't allow using both together.
|
||||
flags &= ~FLAG_ALLOW_WHILE_IDLE;
|
||||
} else if (exact || allowWhileIdle) {
|
||||
final boolean needsPermission;
|
||||
boolean lowerQuota;
|
||||
@@ -2193,55 +2235,11 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
// Repeating alarms must use PendingIntent, not direct listener
|
||||
if (interval != 0) {
|
||||
if (directReceiver != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Repeating alarms cannot use AlarmReceivers");
|
||||
}
|
||||
}
|
||||
|
||||
if (workSource != null) {
|
||||
getContext().enforcePermission(
|
||||
android.Manifest.permission.UPDATE_DEVICE_STATS,
|
||||
Binder.getCallingPid(), callingUid, "AlarmManager.set");
|
||||
}
|
||||
|
||||
// No incoming callers can request either WAKE_FROM_IDLE or
|
||||
// ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
|
||||
flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
|
||||
|
||||
// Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
|
||||
// manager when to come out of idle mode, which is only for DeviceIdleController.
|
||||
if (callingUid != Process.SYSTEM_UID) {
|
||||
flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
|
||||
}
|
||||
|
||||
// If this is an exact time alarm, then it can't be batched with other alarms.
|
||||
if (windowLength == AlarmManager.WINDOW_EXACT) {
|
||||
if (exact) {
|
||||
flags |= AlarmManager.FLAG_STANDALONE;
|
||||
}
|
||||
|
||||
// If this alarm is for an alarm clock, then it must be standalone and we will
|
||||
// use it to wake early from idle if needed.
|
||||
if (alarmClock != null) {
|
||||
flags |= FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
|
||||
|
||||
// If the caller is a core system component or on the user's whitelist, and not calling
|
||||
// to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
|
||||
// This means we will allow these alarms to go off as normal even while idle, with no
|
||||
// timing restrictions.
|
||||
} else if (workSource == null && (UserHandle.isCore(callingUid)
|
||||
|| UserHandle.isSameApp(callingUid, mSystemUiUid)
|
||||
|| ((mAppStateTracker != null)
|
||||
&& mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) {
|
||||
flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
|
||||
flags &= ~FLAG_ALLOW_WHILE_IDLE;
|
||||
flags &= ~FLAG_ALLOW_WHILE_IDLE_COMPAT;
|
||||
flags &= ~FLAG_PRIORITIZE;
|
||||
idleOptions = null;
|
||||
}
|
||||
|
||||
setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
|
||||
listenerTag, flags, workSource, alarmClock, callingUid, callingPackage,
|
||||
idleOptions);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server.alarm;
|
||||
|
||||
import static com.android.server.alarm.AlarmManagerService.TAG;
|
||||
import static com.android.server.alarm.AlarmManagerService.dumpAlarmList;
|
||||
import static com.android.server.alarm.AlarmManagerService.isTimeTickAlarm;
|
||||
|
||||
|
||||
@@ -468,8 +468,9 @@ public class AlarmManagerServiceTest {
|
||||
TEST_CALLING_UID);
|
||||
}
|
||||
|
||||
private void setPrioritizedAlarm(int type, long triggerTime, IAlarmListener listener) {
|
||||
mService.setImpl(type, triggerTime, WINDOW_EXACT, 0, null, listener, "test",
|
||||
private void setPrioritizedAlarm(int type, long triggerTime, long windowLength,
|
||||
IAlarmListener listener) {
|
||||
mService.setImpl(type, triggerTime, windowLength, 0, null, listener, "test",
|
||||
FLAG_STANDALONE | FLAG_PRIORITIZE, null, null, TEST_CALLING_UID,
|
||||
TEST_CALLING_PACKAGE, null);
|
||||
}
|
||||
@@ -1685,7 +1686,7 @@ public class AlarmManagerServiceTest {
|
||||
final int numAlarms = 10;
|
||||
for (int i = 0; i < numAlarms; i++) {
|
||||
setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
|
||||
new IAlarmListener.Stub() {
|
||||
0, new IAlarmListener.Stub() {
|
||||
@Override
|
||||
public void doAlarm(IAlarmCompleteListener callback)
|
||||
throws RemoteException {
|
||||
@@ -1720,7 +1721,7 @@ public class AlarmManagerServiceTest {
|
||||
final int numAlarms = 10;
|
||||
for (int i = 0; i < numAlarms; i++) {
|
||||
setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
|
||||
new IAlarmListener.Stub() {
|
||||
0, new IAlarmListener.Stub() {
|
||||
@Override
|
||||
public void doAlarm(IAlarmCompleteListener callback)
|
||||
throws RemoteException {
|
||||
@@ -1738,12 +1739,12 @@ public class AlarmManagerServiceTest {
|
||||
}
|
||||
assertEquals(numAlarms, alarmsFired.get());
|
||||
|
||||
setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, new IAlarmListener.Stub() {
|
||||
setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, 0, new IAlarmListener.Stub() {
|
||||
@Override
|
||||
public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
|
||||
}
|
||||
});
|
||||
setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, new IAlarmListener.Stub() {
|
||||
setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, 0, new IAlarmListener.Stub() {
|
||||
@Override
|
||||
public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
|
||||
}
|
||||
@@ -2262,6 +2263,28 @@ public class AlarmManagerServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minWindowPriorityAlarm() {
|
||||
doReturn(true).when(
|
||||
() -> CompatChanges.isChangeEnabled(
|
||||
eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS),
|
||||
anyString(), any(UserHandle.class)));
|
||||
final long minWindow = 73;
|
||||
setDeviceConfigLong(KEY_MIN_WINDOW, minWindow);
|
||||
|
||||
// 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC.
|
||||
for (int window = 1; window <= minWindow; window++) {
|
||||
setPrioritizedAlarm(ELAPSED_REALTIME, 0, window, new IAlarmListener.Stub() {
|
||||
@Override
|
||||
public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
|
||||
}
|
||||
});
|
||||
assertEquals(1, mService.mAlarmStore.size());
|
||||
final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0);
|
||||
assertEquals(window, a.windowLength);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void denyListPackagesAdded() {
|
||||
mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"});
|
||||
|
||||
Reference in New Issue
Block a user