By Darryn Campbell
This document details the developer impact of moving to Zebra devices running Android 9.x Pie (API level 28), and is a follow-up to my previous posts about what’s new in Android Oreo, Nougat and Marshmallow. If you are moving from Nougat directly to Pie, I recommend you read the documents in sequence since all the information related to Oreo (e.g. background limitations or changes to the Google Play Store) is also pertinent to Pie.
Audience for This Document
Zebra devices running the SD660 chipset will be receiving an upgrade to Android Pie including the PS20 and the TC52/TC57, TC72/TC77 , TC8300 series. Some models already have a Pie update available, but others will receive one in due course. This list of devices is not exhaustive so please refer to your device’s specification sheet for details of the processor. Any developers targeting deployments featuring at least one Pie device or devices that will be updated to Pie should be aware of the changes detailed here.
As with each new version of Android, Pie introduces many new features, changes and enhancements that developers should be aware of before transitioning their applications to this new OS dessert. Google emphasises the artificial intelligence aspects of Android 9, and nowhere is that more evident than in the changes made to power management discussed in detail in this document. This release also continues the recent trend to add new features intended specifically for enterprise devices.
Google has published detailed overviews of the Pie changes on its developer portal. They’re broken down this way:
- Features and APIs
- Behavioural changes affecting all applications
- Behavioural changes only affecting applications targeting API level 28+
Google also has published detailed information around the changes to power management (including a table showing all power management restrictions) and an article that focuses on the specific changes made for enterprise devices & apps. There are many changes that affect all applications regardless of your target SDK, so even if you do not plan on making changes, it is strongly recommended by both Zebra and Google that you familiarize yourself with your application’s behavior on Pie and test it on the new OS.
This document does not replace recommendations from Google; it is designed to supplement those recommendations for enterprise use cases.
Power Management Changes
All versions of Android since Marshmallow have introduced some form of restriction on what applications can do in the background along with corresponding APIs and advice on how to develop an application to work with those restrictions in mind. All the changes—from Marshmallow’s Doze mode and Nougat’s enhanced Doze mode to Oreo’s background restrictions—have been cumulative, and the power-management changes in Pie are no exception. It is understandably quite daunting for any developer to try and fully understand everything that Android might do to stop their application running (and consuming battery) in the background and Google has addressed this with increasingly capable classes to defer your background work and schedule it to be done when some set of conditions are met (e.g. when the device is charging).
I have personally found that many of Zebra's enterprise customers want to understand the minutiae of device power management. This is understandable given the long lifecycles of enterprise applications combined with use cases that are quite different from consumer applications. However, an equal number of developers want something that "just works’ regardless of which device OS they are running on. I will try and cater to both groups by explaining the changes to power management in Pie before exploring the direction Google is moving in with the Work Manager class.
Standby Buckets & Adaptive Battery
Google first announced adaptive battery as part of its 2018 Pie preview whereby applications were categorized into “buckets.” Based on how frequently apps are used and which bucket they are in controls how much power that application is allowed to consume. The feature “App standby buckets” is an enhancement to the “App Standby" feature first introduced in Marshmallow. Where App Standby allows an app only to be either active or inactive, app standby buckets allow for far greater granularity.
As is detailed in the official documentation, the possible buckets into which an application can be placed and the effects of being in that bucket are explained briefly as follows:
User is currently engaged with the application and Android considers it to be in the foreground
Application is not currently active but runs often.
Application is used regularly but not necessarily every day.
Restrictions: Jobs and Alarms will be deferred for longer than applications in the working set. No restrictions on network access but Firebase Cloud Messaging is limited to 10 high-priority messages per day.
Application is not used often.
Restrictions: Jobs and Alarms will be deferred for longer than applications in the frequent set. Network access is deferred and Firebase Cloud Messaging is limited to 5 high-priority messages per day.
Application has been installed but never run.
“The system imposes severe restrictions on these apps.”
Remember, these restrictions are in addition to other Android background restrictions. So for example, even if the application is in the working set, it’s also subject to Doze mode restrictions.
There is no API to request that an application be placed into a particular bucket, so a developer has little influence on where Android will put their app. However, the UsageStagsManager.getAppStandbyBucket() method is provided to determine which bucket an app is currently in. Application buckets are assigned and reassigned by Android as needed.
Applications on the Doze-mode whitelist are exempted from bucket-based restrictions. Through its MX Management Framework, Zebra exposes the capability during staging to either add an application to the whitelist or disable Doze mode entirely. Here’s how:
- To add an application to the Doze-mode whitelist, the App Manager’s actions can be used on devices with MX 7.0 or higher.
- To disable Doze mode entirely on your device then the Power Manager’s "" action can be used.
Note that “Remove Application for Battery Optimization” is analogous to adding the application to the whitelist. For more information on “BatteryOptimization” please see the relevant section of the MX AppManager documentation.
Whitelisting your application or disabling Doze mode can increase the battery consumption of the device. For more information on whitelisting and background applications, please see the article on keeping your application running when the device wants to sleep.
For testing purposes, you can use adb to manually assign your app to an App Standby Bucket. To change an app’s bucket, use the following commands (as detailed in the Android docs):
$ adb shell am set-standby-bucket packagename active|working_set|frequent|rare
You can also use that command to set multiple packages at once:
$ adb shell am set-standby-bucket package1 bucket1 package2 bucket2...
To determine which bucket an app is in, run:
$ adb shell am get-standby-bucket [packagename]
If you don't pass a packagename parameter, the command lists the buckets for all apps.
Device developer options also allow you to see which bucket each application is in from Settings à System à Developer Options à Standby apps.
The Application Restrictions feature is an evolution of Oreo’s background limits, but is more strict in Pie. An application in the background running on Oreo can receive Firebase Cloud Messages, but that same app—if restricted in P—will not receive any FCM messages regardless of their priority. Until it comes into the foreground, an application on Pie that is restricted will never have Jobs or Alarms fire, will have no access to the network or device location, and will not be able to receive Firebase Cloud Messages. App restrictions are designed as a way for the user to limit what an application can do in the background, so enterprises will typically want to prevent the user from configuring this.
Applications are restricted by the user either by:
- Restricting the app from the "Battery usage’ settings UI for that app (Settings à Apps & notifications à [Select App] à Advanced à Battery à Background restriction).
- Selecting to restrict the app from the list of misbehaving applications which Android automatically generates. This list can be seen on the battery settings screen (Settings à Battery) and will only allow users to restrict applications what have been deemed to be using excessive background battery. The criteria for an application appearing here is “excessive behaviour over certain thresholds,” such as excessive wakelocks. But those thresholds are not documented and OEMs can add custom criteria (Zebra has not made any changes in this area). An application being added to this list does not automatically restrict the app and manual intervention by the user is still required before any restriction is enforced.
Android has detected a single application is using excessive battery in the background.
There is no way to remotely detect that a particular application has been restricted. Note that the terminology in the Device Policy Manager (EMM) documentation can be confusing since "Application Restrictions" is a completely separate feature. Android Vitals can report many of the same problems that lead to an application being considered to be using excessive background battery, e.g. excessive wake locks and administrators deploying their applications via the managed Play Store could consider using Android Vitals.
Author’s Comment: I tried to write an application that would misbehave and reproduce this warning to add colour to what "excessive behaviour" meant but was unable to do so despite multiple attempts with wake locks, alarms, background work and background services. I suspect that in most cases, other Android features that restrict background work may come into play before an application is deemed to have excessive use. The detection policy appears to be related to AnomalyDetectionPolicy.java which covers alarms, wake locks and Bluetooth scans. In the end I had to resort to using a 3rd party application to generate the above screenshot.
You can view the restricted apps from the Adaptive Battery screen (Settings à Battery à Adaptive Battery à Restricted apps). Note that if you have not restricted any apps, then the “Restricted apps” option will not show on the Adaptive Battery screen.
Most enterprises will want their line of business applications never to be restricted. To achieve this, ensure the appropriate settings screens are not available to the end user. There are many ways to achieve this; a few are listed below.
- Zebra’s Enterprise Home Screen application can reduce the available settings to the user.
- Zebra’s MX Access Manager can restrict access to device settings during staging.
- Many EMM solutions offer the ability to lock down the device settings from the end user.
- Kiosk features of Android Enterprise can be used for task-specific devices.
For more information, please see Locking Down Your Device, an article on Zebra’s Developer Portal.
Battery Saver improvements
Battery Saver applies restrictions to all applications on the device. When turned on, Battery Saver takes steps to reduce battery consumption such as stopping all applications from performing background work and disallowing network access to any application not in the foreground. The best official documentation is on Google’s Battery Saver support page.
Battery Saver is not new to Pie, but it has been improved in a couple of ways worth highlighting here since I notice some external blogs conflate “Battery Saver” with the other App restrictions when discussing Pie.
Although disabled out of the box, Battery Saver can either be turned on manually by the user or be configured to turn on automatically at some specified battery percentage (15% by default).
The Settings à Battery à Battery Saver screen on Pie.
The table below compares the behaviour of Battery Saver on Oreo and Pie
Off; Battery Saver does not automatically enable
Off; Battery Saver does not automatically enable
How to manually enable
From the Battery Saver menu (Settings à Battery à Battery Saver) or Quick Settings icon
From the Battery Saver menu (Settings à Battery à Battery Saver) or Quick Settings icon
Supported "turn on automatically at X%" percentages
Supports only 10% or 18%
Configurable from 5% to 75%
How to turn off Battery Saver
Manually from Battery Saver menu / Quick Settings icon or by providing power to the device
Manually from the Battery Saver menu / Quick Settings icon.
Providing power to the device only disables Battery Saver while power is applied
Most enterprises using Oreo and wishing to disable end-user access to the Battery Saver would have already locked down access to the device’s quick settings icons as well as the Battery settings screen. For more information on locking down your device, please refer to the earlier section on “App Restrictions."
You can use adb to manually control Battery Saver (as detailed in the Android docs):
To simulate the device being unplugged:
$ adb shell dumpsys battery unplug
To test how the device behaves under low power conditions:
$ adb shell settings put global low_power 1
Once you have finished your testing, you can undo your manual device settings:
$ adb shell dumpsys battery reset
Summary of Pie Power Management Changes
Google has given more user control over how applications use the battery. This includes allowing users to restrict individual applications and allowing the behaviour of the user to influence which app-standby bucket the application is placed in. In general, enterprises should limit what the user can do rather than give more control. But since most Zebra customers already use some form of lock-down over device settings, and Zebra offers full configurability over Doze mode, the actual implications of the new Background restrictions in Pie should be minimal for most Zebra customers. Bear in mind that power management changes will affect all applications on the device, not just those targeting API level 28+. So all developers should familiarize themselves with these changes.
To learn more about the details of the power management changes in Pie, I strongly recommend watching “Improving Battery Life with Restrictions,” a presentation from Google’s Android DevSummit in Nov., 2018. The presentation very clearly explains the specifics of how Alarms, Jobs and push messages behave with the different power restrictions.
Screenshots from “Improving Battery Life with Restrictions,” a presentation from Google’s Android DevSummit in Nov., 2018, which illustrate how the different power management restrictions affect different aspects of applications.
Scheduling background work on Android also has evolved. Google offers a guide to scheduling jobs which covers JobScheduler, AlarmManager, JobDispatcher and some other APIs, but the current advice is to start transitioning your background work to the new WorkManager class. WorkManager is designed to “replace” the previous APIs, although under the covers it is using the existing implementation. As a developer, you don’t have to worry about how the jobs are scheduled, you just care that they are.
I would recommend browsing the Google resources for WorkManager as well as a good article by the developer relations team on "modern background execution in Android." There are also a couple of good video resources: either the 6-minute introduction video or “Working with WorkManager,” a session from the Android Dev Summit in Nov., 2018.
From an enterprise point of view, the advice has always been to work with the changes Google is making to power management in Android wherever possible. WorkManager is an easy way to work with changes such as background restrictions and Doze mode without having to worry about the details. The trade-off is that background work might not occur at exactly the desired time, but the benefit is extended battery duration. I have personally used WorkManager in a few of my projects and have found it intuitive. However, if your use cases require applications to remain running continually in the background, WorkManager is not suitable for you, and you might be helped by the guidance I provided in “Keeping your Android application running when the device wants to sleep” on the Zebra developer portal.
Android Enterprise Behaviour Changes
Google has an entire page on its developer portal dedicated to the new features of Android Enterprise added in Android 9. Many of these features, such as the changes to the default launcher, switching apps across profiles and configuring the work profile lock screen challenge, are targeted at BYOD devices. Among the Android Enterprise additions, there also are some major developments targeted at task-specific devices (which is the category Zebra devices fall into), including enhancements to lock task mode and the introduction of ephemeral users, both of which are worth a much closer look.
In Oreo, it was necessary to specifically add lock-task mode support to an application either by calling startLockTask() or by specifying lockTaskMode in the application manifest. There are videos and descriptions of the behaviour of an application with these methods in the developer-portal post on locking down your device.
Under Pie, a Device Owner (DO) or Profile Owner (most typically an EMM is running in DO mode for our customer base) has the ability to put any whitelisted application into lock task mode using ActivityOptions.setLockTaskEnabled(boolean). Doing so enables any application to act in a "kiosk mode" environment without modification. For example, imagine my application wants the user to choose an image from the device gallery. As long as my application and the gallery application are whitelisted, my app can call startActivityForResult() and the user can pick the picture. At no point is the user given access to any button other than the back button (unless you use one of the new flags discussed in the next paragraph).
Lock task mode has been made far more configurable under Pie and is no longer restricted to displaying only the back button (as was the case under Oreo). Several new flags have been defined that a DO can pass to DevicePolicyManager.setLockTaskFeatures(flags). This is best illustrated with screenshots:
The default state, same as not applying kiosk mode
Shows the time, Wi-Fi and battery icons, and the back button
Shows the home and back buttons (whitelist the launcher and set a default launcher for the home button work). Only whitelisted applications can be launched.
Enables the notification shade to be pulled down. The application that created the notification need not be whitelisted for its notification to be displayed. The quick settings panel remains disabled.