Loading apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +6 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,10 @@ class Alarm { * Change wasn't enable for the caller due to compat reasons. */ static final int EXACT_ALLOW_REASON_COMPAT = 2; /** * Caller had USE_EXACT_ALARM permission. */ static final int EXACT_ALLOW_REASON_POLICY_PERMISSION = 3; public final int type; /** Loading Loading @@ -275,6 +279,8 @@ class Alarm { return "compat"; case EXACT_ALLOW_REASON_PERMISSION: return "permission"; case EXACT_ALLOW_REASON_POLICY_PERMISSION: return "policy_permission"; case EXACT_ALLOW_REASON_NOT_APPLICABLE: return "N/A"; default: Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +35 −36 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION; import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX; import static com.android.server.alarm.Alarm.TARE_POLICY_INDEX; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED; Loading Loading @@ -2698,8 +2699,7 @@ public class AlarmManagerService extends SystemService { // Make sure the caller is allowed to use the requested kind of alarm, and also // decide what quota and broadcast options to use. boolean allowListed = false; // For logging the reason. boolean changeDisabled = false; // For logging the reason. int exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE; Bundle idleOptions = null; if ((flags & FLAG_PRIORITIZE) != 0) { getContext().enforcePermission( Loading @@ -2721,57 +2721,56 @@ public class AlarmManagerService extends SystemService { idleOptions = mOptsWithoutFgs.toBundle(); } } else { changeDisabled = true; needsPermission = false; lowerQuota = allowWhileIdle; idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null; if (exact) { exactAllowReason = EXACT_ALLOW_REASON_COMPAT; } if (needsPermission && !hasScheduleExactAlarmInternal(callingPackage, callingUid) && !hasUseExactAlarmInternal(callingPackage, callingUid)) { if (!isExemptFromExactAlarmPermissionNoLock(callingUid)) { final String errorMessage = "Caller " + callingPackage + " needs to hold " + Manifest.permission.SCHEDULE_EXACT_ALARM + " to set " } if (needsPermission) { if (hasUseExactAlarmInternal(callingPackage, callingUid)) { exactAllowReason = EXACT_ALLOW_REASON_POLICY_PERMISSION; } else if (hasScheduleExactAlarmInternal(callingPackage, callingUid)) { exactAllowReason = EXACT_ALLOW_REASON_PERMISSION; } else { if (isExemptFromExactAlarmPermissionNoLock(callingUid)) { exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST; } else { final String errorMessage = "Caller " + callingPackage + " needs to hold " + Manifest.permission.SCHEDULE_EXACT_ALARM + " or " + Manifest.permission.USE_EXACT_ALARM + " to set " + "exact alarms."; if (mConstants.CRASH_NON_CLOCK_APPS) { throw new SecurityException(errorMessage); } else { Slog.wtf(TAG, errorMessage); } } else { allowListed = true; } // If the app is on the full system power allow-list (not except-idle), or the // user-elected allow-list, or we're in a soft failure mode, we still allow the // alarms. // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to what // pre-S apps got. Note that user-allow-listed apps don't use the flag // If the app is on the full system power allow-list (not except-idle), // or the user-elected allow-list, or we're in a soft failure mode, we still // allow the alarms. // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to // what pre-S apps got. Note that user-allow-listed apps don't use the flag // ALLOW_WHILE_IDLE. // We grant temporary allow-list to allow-while-idle alarms but without FGS // capability. AlarmClock alarms do not get the temporary allow-list. This is // consistent with pre-S behavior. Note that apps that are in either of the // power-save allow-lists do not need it. // capability. AlarmClock alarms do not get the temporary allow-list. // This is consistent with pre-S behavior. Note that apps that are in // either of the power-save allow-lists do not need it. idleOptions = allowWhileIdle ? mOptsWithoutFgs.toBundle() : null; lowerQuota = allowWhileIdle; } } if (lowerQuota) { flags &= ~FLAG_ALLOW_WHILE_IDLE; flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT; } } final int exactAllowReason; if (exact) { // If this is an exact time alarm, then it can't be batched with other alarms. flags |= AlarmManager.FLAG_STANDALONE; if (changeDisabled) { exactAllowReason = EXACT_ALLOW_REASON_COMPAT; } else if (allowListed) { exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST; } else { exactAllowReason = EXACT_ALLOW_REASON_PERMISSION; } } else { exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE; } setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver, Loading apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java +3 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED; import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE; import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION; import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION; import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY; import android.app.ActivityManager; Loading Loading @@ -89,6 +90,8 @@ class MetricsHelper { return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION; case Alarm.EXACT_ALLOW_REASON_COMPAT: return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED; case Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION: return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION; default: return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE; } Loading services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +85 −3 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION; import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX; import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED; import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED; Loading Loading @@ -2337,7 +2338,7 @@ public class AlarmManagerServiceTest { } @Test public void alarmClockBinderCall() throws RemoteException { public void alarmClockBinderCallWithSEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockScheduleExactAlarmState(true, false, MODE_ALLOWED); Loading @@ -2362,6 +2363,34 @@ public class AlarmManagerServiceTest { assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void alarmClockBinderCallWithUEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); mockUseExactAlarmState(true); mockScheduleExactAlarmState(false, false, MODE_ERRORED); final PendingIntent alarmPi = getNewMockPendingIntent(); final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class); mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0, alarmPi, null, null, null, alarmClock); // Correct permission checks are invoked. verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE), isNull(), eq(alarmClock), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); final int type = idleOptions.getTemporaryAppAllowlistType(); assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } private void mockScheduleExactAlarmState(boolean declared, boolean denyList, int mode) { String[] requesters = declared ? new String[]{TEST_CALLING_PACKAGE} : EmptyArray.STRING; when(mPermissionManagerInternal.getAppOpPermissionPackages(SCHEDULE_EXACT_ALARM)) Loading Loading @@ -2410,7 +2439,7 @@ public class AlarmManagerServiceTest { } @Test public void exactBinderCallWithPermission() throws RemoteException { public void exactBinderCallWithSEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockScheduleExactAlarmState(true, false, MODE_ALLOWED); Loading @@ -2433,6 +2462,32 @@ public class AlarmManagerServiceTest { assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactBinderCallWithUEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); mockUseExactAlarmState(true); mockScheduleExactAlarmState(false, false, MODE_ERRORED); final PendingIntent alarmPi = getNewMockPendingIntent(); mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 0, alarmPi, null, null, null, null); verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE), isNull(), isNull(), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); final int type = idleOptions.getTemporaryAppAllowlistType(); assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactBinderCallWithAllowlist() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); Loading @@ -2454,7 +2509,7 @@ public class AlarmManagerServiceTest { } @Test public void exactAllowWhileIdleBinderCallWithPermission() throws RemoteException { public void exactAllowWhileIdleBinderCallWithSEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockScheduleExactAlarmState(true, false, MODE_ALLOWED); Loading @@ -2462,6 +2517,7 @@ public class AlarmManagerServiceTest { mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); Loading @@ -2476,6 +2532,32 @@ public class AlarmManagerServiceTest { assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactAllowWhileIdleBinderCallWithUEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); mockUseExactAlarmState(true); mockScheduleExactAlarmState(false, false, MODE_ERRORED); final PendingIntent alarmPi = getNewMockPendingIntent(); mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), eq(alarmPi), isNull(), isNull(), eq(FLAG_ALLOW_WHILE_IDLE | FLAG_STANDALONE), isNull(), isNull(), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); final int type = idleOptions.getTemporaryAppAllowlistType(); assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); Loading Loading
apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +6 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,10 @@ class Alarm { * Change wasn't enable for the caller due to compat reasons. */ static final int EXACT_ALLOW_REASON_COMPAT = 2; /** * Caller had USE_EXACT_ALARM permission. */ static final int EXACT_ALLOW_REASON_POLICY_PERMISSION = 3; public final int type; /** Loading Loading @@ -275,6 +279,8 @@ class Alarm { return "compat"; case EXACT_ALLOW_REASON_PERMISSION: return "permission"; case EXACT_ALLOW_REASON_POLICY_PERMISSION: return "policy_permission"; case EXACT_ALLOW_REASON_NOT_APPLICABLE: return "N/A"; default: Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +35 −36 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION; import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX; import static com.android.server.alarm.Alarm.TARE_POLICY_INDEX; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED; Loading Loading @@ -2698,8 +2699,7 @@ public class AlarmManagerService extends SystemService { // Make sure the caller is allowed to use the requested kind of alarm, and also // decide what quota and broadcast options to use. boolean allowListed = false; // For logging the reason. boolean changeDisabled = false; // For logging the reason. int exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE; Bundle idleOptions = null; if ((flags & FLAG_PRIORITIZE) != 0) { getContext().enforcePermission( Loading @@ -2721,57 +2721,56 @@ public class AlarmManagerService extends SystemService { idleOptions = mOptsWithoutFgs.toBundle(); } } else { changeDisabled = true; needsPermission = false; lowerQuota = allowWhileIdle; idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null; if (exact) { exactAllowReason = EXACT_ALLOW_REASON_COMPAT; } if (needsPermission && !hasScheduleExactAlarmInternal(callingPackage, callingUid) && !hasUseExactAlarmInternal(callingPackage, callingUid)) { if (!isExemptFromExactAlarmPermissionNoLock(callingUid)) { final String errorMessage = "Caller " + callingPackage + " needs to hold " + Manifest.permission.SCHEDULE_EXACT_ALARM + " to set " } if (needsPermission) { if (hasUseExactAlarmInternal(callingPackage, callingUid)) { exactAllowReason = EXACT_ALLOW_REASON_POLICY_PERMISSION; } else if (hasScheduleExactAlarmInternal(callingPackage, callingUid)) { exactAllowReason = EXACT_ALLOW_REASON_PERMISSION; } else { if (isExemptFromExactAlarmPermissionNoLock(callingUid)) { exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST; } else { final String errorMessage = "Caller " + callingPackage + " needs to hold " + Manifest.permission.SCHEDULE_EXACT_ALARM + " or " + Manifest.permission.USE_EXACT_ALARM + " to set " + "exact alarms."; if (mConstants.CRASH_NON_CLOCK_APPS) { throw new SecurityException(errorMessage); } else { Slog.wtf(TAG, errorMessage); } } else { allowListed = true; } // If the app is on the full system power allow-list (not except-idle), or the // user-elected allow-list, or we're in a soft failure mode, we still allow the // alarms. // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to what // pre-S apps got. Note that user-allow-listed apps don't use the flag // If the app is on the full system power allow-list (not except-idle), // or the user-elected allow-list, or we're in a soft failure mode, we still // allow the alarms. // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to // what pre-S apps got. Note that user-allow-listed apps don't use the flag // ALLOW_WHILE_IDLE. // We grant temporary allow-list to allow-while-idle alarms but without FGS // capability. AlarmClock alarms do not get the temporary allow-list. This is // consistent with pre-S behavior. Note that apps that are in either of the // power-save allow-lists do not need it. // capability. AlarmClock alarms do not get the temporary allow-list. // This is consistent with pre-S behavior. Note that apps that are in // either of the power-save allow-lists do not need it. idleOptions = allowWhileIdle ? mOptsWithoutFgs.toBundle() : null; lowerQuota = allowWhileIdle; } } if (lowerQuota) { flags &= ~FLAG_ALLOW_WHILE_IDLE; flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT; } } final int exactAllowReason; if (exact) { // If this is an exact time alarm, then it can't be batched with other alarms. flags |= AlarmManager.FLAG_STANDALONE; if (changeDisabled) { exactAllowReason = EXACT_ALLOW_REASON_COMPAT; } else if (allowListed) { exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST; } else { exactAllowReason = EXACT_ALLOW_REASON_PERMISSION; } } else { exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE; } setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver, Loading
apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java +3 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED; import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE; import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION; import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION; import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY; import android.app.ActivityManager; Loading Loading @@ -89,6 +90,8 @@ class MetricsHelper { return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION; case Alarm.EXACT_ALLOW_REASON_COMPAT: return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED; case Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION: return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION; default: return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE; } Loading
services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +85 −3 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION; import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION; import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX; import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED; import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED; Loading Loading @@ -2337,7 +2338,7 @@ public class AlarmManagerServiceTest { } @Test public void alarmClockBinderCall() throws RemoteException { public void alarmClockBinderCallWithSEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockScheduleExactAlarmState(true, false, MODE_ALLOWED); Loading @@ -2362,6 +2363,34 @@ public class AlarmManagerServiceTest { assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void alarmClockBinderCallWithUEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); mockUseExactAlarmState(true); mockScheduleExactAlarmState(false, false, MODE_ERRORED); final PendingIntent alarmPi = getNewMockPendingIntent(); final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class); mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0, alarmPi, null, null, null, alarmClock); // Correct permission checks are invoked. verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE), isNull(), eq(alarmClock), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); final int type = idleOptions.getTemporaryAppAllowlistType(); assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } private void mockScheduleExactAlarmState(boolean declared, boolean denyList, int mode) { String[] requesters = declared ? new String[]{TEST_CALLING_PACKAGE} : EmptyArray.STRING; when(mPermissionManagerInternal.getAppOpPermissionPackages(SCHEDULE_EXACT_ALARM)) Loading Loading @@ -2410,7 +2439,7 @@ public class AlarmManagerServiceTest { } @Test public void exactBinderCallWithPermission() throws RemoteException { public void exactBinderCallWithSEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockScheduleExactAlarmState(true, false, MODE_ALLOWED); Loading @@ -2433,6 +2462,32 @@ public class AlarmManagerServiceTest { assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactBinderCallWithUEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); mockUseExactAlarmState(true); mockScheduleExactAlarmState(false, false, MODE_ERRORED); final PendingIntent alarmPi = getNewMockPendingIntent(); mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 0, alarmPi, null, null, null, null); verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE), isNull(), isNull(), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); final int type = idleOptions.getTemporaryAppAllowlistType(); assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactBinderCallWithAllowlist() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); Loading @@ -2454,7 +2509,7 @@ public class AlarmManagerServiceTest { } @Test public void exactAllowWhileIdleBinderCallWithPermission() throws RemoteException { public void exactAllowWhileIdleBinderCallWithSEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockScheduleExactAlarmState(true, false, MODE_ALLOWED); Loading @@ -2462,6 +2517,7 @@ public class AlarmManagerServiceTest { mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); Loading @@ -2476,6 +2532,32 @@ public class AlarmManagerServiceTest { assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactAllowWhileIdleBinderCallWithUEAPermission() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); mockUseExactAlarmState(true); mockScheduleExactAlarmState(false, false, MODE_ERRORED); final PendingIntent alarmPi = getNewMockPendingIntent(); mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), eq(alarmPi), isNull(), isNull(), eq(FLAG_ALLOW_WHILE_IDLE | FLAG_STANDALONE), isNull(), isNull(), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); final int type = idleOptions.getTemporaryAppAllowlistType(); assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); } @Test public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException { mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); Loading