Android 13 adds a number of app-facing behavioral changes and APIs that tweak how apps can do work in the background, but not all of these changes were mentioned by Google at I/O earlier this month. For example, Android 13 places new restrictions on which apps can schedule exact alarms, a change that is designed to improve battery life but may break functionality in apps that are unprepared.
Background work and alarms
Apps that want to perform work in the background (i.e. while the app isn’t visible to the user) have a few options on Android. Google recommends using the WorkManager API to do most work in the background, which internally uses the system JobScheduler service to schedule tasks. Work that’s scheduled this way will execute at some point in the future, the timing of which is determined by the information sent to the JobScheduler service when scheduling the work as well as device signals like the charging or network state. Knowing how and when to schedule background work is important for app developers to understand because most Android devices run on battery power.
Sometimes, though, apps can’t rely on WorkManager to perform work, because the work that needs to be done has to be done at a very specific point in time. Apps can’t tell the system exactly when to execute its work through WorkManager, because it wasn’t designed for that purpose. Instead, apps are encouraged to use Android’s AlarmManager API, which lets apps schedule “alarms” that run at set times.
When the system invokes the alarm at the set time, apps can basically do whatever work they want. Alarm clock and calendar apps depend on the AlarmManager API for their core functionality, for example. Without this API, an alarm clock app wouldn’t be able to fire off an alarm the user set for 06:00 AM unless the user had the app open at that time or the app had a foreground service running. Likewise, a calendar app wouldn’t be able to notify the user about a meeting they scheduled for 2:00 PM without the use of AlarmManager.
These kinds of alarms — called exact alarms — have the ability to bring the device out of “Doze mode,” one of Android’s core battery-saving restrictions. Doze mode is a low-power idle state that prevents most background activity from happening outside of recurring “maintenance windows.” Thus, if too many apps schedule exact alarms at different times, then the device won’t be idling for very long, reducing the overall battery life.
This is why the AlarmManager API provides for scheduling inexact alarms, which are delivered by the system within a window of the trigger time specified by the app. Apps are encouraged to schedule inexact alarms when possible to minimize system resource consumption, but until Android 13, there was nothing really limiting apps from scheduling resource-heavy exact alarms.
Requiring permission to schedule exact alarms
In Android 12, Google introduced a new permission called “SCHEDULE_EXACT_ALARM” that apps must hold in order to schedule exact alarms (hence the name). Apps targeting API level 31 (Android 12) or higher holding this permission are able to use the exact alarm APIs provided by AlarmManager, including setExact and setExactAndAllowWhileIdle. Apps targeting API level 31 or higher that don’t hold the SCHEDULE_EXACT_ALARM permission aren’t able to use these APIs unless those apps have been exempted from battery restrictions. Lastly, apps targeting API level 30 (Android 11) or lower don’t need to hold this permission to use exact alarm APIs.
When Google introduced the SCHEDULE_EXACT_ALARM permission in Android 12, they set its protection level to “normal|appop”. Thus, apps requesting this permission on Android 12 were automatically granted it at install time, though the user could revoke it post-installation via the AppOpsManager CLI or by going to Settings > Apps > Special app access > Alarms & reminders. Though the developer docs say that exact alarms “should only be used for user-facing features” and that there are only two acceptable use cases for using them, the Android platform treats this as a suggestion rather than a rule. That will change in Android 13, however.
Android 13 will deny the SCHEDULE_EXACT_ALARM permission by default for apps targeting API level 33. The protection level of this permission has been changed from “normal|appop” to just “appop” in Android 13, hence it is no longer automatically granted at install time for all apps that request it. However, Android 13 will automatically grant the permission to all apps targeting API level 31-32 in order to maintain backward compatibility. This means that apps targeting API level 33 running on Android 13 will need to explicitly ask the user for permission before they can schedule exact alarms.
This is not a significant hurdle to overcome, but it does mean that apps that don’t already follow best practices by checking if they have access to exact alarm APIs before calling them will run into trouble. Apps that need this functionality are encouraged to call AlarmManager’s canScheduleExactAlarms API to see if they’re allowed to schedule exact alarms. If they aren’t allowed to do so, then they can start android.settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM to bring the user directly to their app’s page in “Alarms & reminders.”
Alternatively, developers can request their users to exempt their apps from battery restrictions so their apps can use exact alarm APIs regardless of the SCHEDULE_EXACT_ALARM permission. They can either ask users to exempt their apps manually by going to Settings > Apps > App info > Battery and selecting “unrestricted,” or they can declare the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission and start android.settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS to prompt users to ignore battery optimizations without opening Settings. Note that Google Play policies prohibit most apps from directly requesting exemptions to battery restrictions, so it’s not wise to go this route unless Google explicitly gave permission.
There is another way to gain access to exact alarm APIs that’s exclusive to Android 13, but it’s only allowed for specific types of apps. Android 13 added a new permission called USE_EXACT_ALARM that, like SCHEDULE_EXACT_ALARM, lets its holders call exact alarm APIs. Unlike SCHEDULE_EXACT_ALARM, however, USE_EXACT_ALARM in Android 13 has a protection level of “normal”, meaning it is granted at install time and cannot be revoked without uninstallation. While any app targeting API level 33 can request and be granted this permission, the developer docs warn that “an upcoming Google Play policy will prevent apps from using the USE_EXACT_ALARM permission” unless they fall into one of the following categories:
- The app is an alarm app or clock app
- The app is a calendar app that shows notifications for upcoming events
If the app requesting the USE_EXACT_ALARM permission doesn’t fall into one of these categories, then Google Play won’t allow the app to be published. If you’ll recall, these categories match the two acceptable use cases for setting an exact alarm mentioned earlier. While Google only recommended that the use of exact alarm APIs be limited to alarm, clock, and calendar apps in Android 12, the company is taking steps to enforce this behavior in Android 13. Soon, most apps will be unable to use exact alarm APIs by default, and those that want to do so will need explicit approval from the user. By adding this step, some developers will be forced to evaluate if they truly need to set exact alarms, and some users will be asking themselves if they should grant this permission to apps that request it. The result may be a reduction in apps scheduling exact alarms, thus improving battery life.
Currently an undocumented change?
The developer docs do not mention the aforementioned changes to the SCHEDULE_EXACT_ALARM permission in Android 13, only that “all apps using exact alarms for secondary features (which should still be user facing) should continue using this permission” and to “be prepared for the situation where the user denies access.” The Android 13 preview builds confirm the changes are coming, however.
Within the updated AlarmManagerService code is a new method called isScheduleExactAlarmDeniedByDefault, which returns “true” if both the constant SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT and the app compatibility change by the same name are set to true.
The boolean constant SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT is hardcoded to true in AlarmManagerService, but the app compatibility change is only enabled for apps targeting API level 33 or later. The App Compatibility Changes page, by the way, pulls its list from XMLs in /system/etc/compatconfig. The developer docs do not list every compatibility change that is available in developer options, but these XMLs do. The SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT app compatibility change, for example, can be found in framework-platform-compat-config.xml, and it reads as follows:
Google will hopefully update its developer docs soon to reflect this change in Android 13. In the meantime, developers who rely on exact alarm APIs should update their apps in preparation for Android 13’s release. Developers building an alarm clock or calendar app should declare the new USE_EXACT_ALARM permission. Other developers should add an in-app explanation for why users should grant the SCHEDULE_EXACT_ALARM permission. Users, meanwhile, should audit apps requesting the SCHEDULE_EXACT_ALARM permission by going to Settings > Apps > Special app access > Alarms & reminders.
Hero image source: agrofruti/Shutterstock.com