diff options
author | 2020-10-22 14:32:56 -0700 | |
---|---|---|
committer | 2020-10-28 18:45:22 +0000 | |
commit | 705e7865e716f1a1060eb501c9e720e29404bbac (patch) | |
tree | db2db1edb975860a7ecc68a85f25c755da4dbea9 | |
parent | 0583d29f136d16793bcc5d74beb21431d364b2d8 (diff) |
Add sync manager documentation on app-standby exemption
Also fix the command line flag help for "adb shell requestsync".
Bug: n/a
Test: n/a, doc only change
Change-Id: I53ad0cae99d30050d1cd8bab349096605865b9fc
3 files changed, 127 insertions, 3 deletions
diff --git a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java index 8683ca163fb6..a0361d0a39d3 100644 --- a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java +++ b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java @@ -294,9 +294,9 @@ public class RequestSync { " -a|--authority <AUTHORITY>\n" + " App-standby related options\n" + "\n" + - " -f|--foreground (cause WORKING_SET, FREQUENT sync adapters" + - " to run immediately)\n" + - " -F|--top (cause even RARE sync adapters to run immediately)\n" + + " -f|--foreground (defeat app-standby job throttling," + + " but not battery saver)\n" + + " -F|--top (defeat app-standby job throttling and battery saver)\n" + " ContentResolver extra options:\n" + " --is|--ignore-settings: Add SYNC_EXTRAS_IGNORE_SETTINGS\n" + " --ib|--ignore-backoff: Add SYNC_EXTRAS_IGNORE_BACKOFF\n" + diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index c686ba4c4b5c..853edcac0833 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -151,6 +151,8 @@ import java.util.function.Predicate; * run at a later time. Similarly, when a sync succeeds, backoff is cleared and all associated syncs * are rescheduled. A rescheduled sync will get a new jobId. * + * See also {@code SyncManager.md} in the same directory for how app-standby affects sync adapters. + * * @hide */ public class SyncManager { diff --git a/services/core/java/com/android/server/content/SyncManager.md b/services/core/java/com/android/server/content/SyncManager.md new file mode 100644 index 000000000000..8507abdcc40e --- /dev/null +++ b/services/core/java/com/android/server/content/SyncManager.md @@ -0,0 +1,122 @@ +# Sync Manager notes + +## App-standby and Sync Manager + +Android 9 Pie introduced +["App Standby Buckets"](https://developer.android.com/topic/performance/appstandby), which throttles various things +including +[JobScheduler](https://developer.android.com/reference/android/app/job/JobScheduler) +and [AlarmManager](https://developer.android.com/reference/android/app/AlarmManager), +[among other things](https://developer.android.com/topic/performance/power/power-details), +for background applications. + +Because SyncManager executes sync operations as JobScheduler jobs, sync operations are subject +to the same throttling. + +However, unlike JobScheduler jobs, any apps (with the proper permission) can schedule a sync +operation in any other apps using +[ContentResolver.requestSync()](https://developer.android.com/reference/android/content/ContentResolver#requestSync(android.content.SyncRequest)), +whch means it's possible for a foreground app to request a sync in another app that is either in the +background or is not even running. +For example, when the user hits the refresh button on the Contacts app, it'll +request sync to all the contacts sync adapters, which are implemented in other packages (and they're +likely not in the foreground). + +Because of this, calls to +[ContentResolver.requestSync()](https://developer.android.com/reference/android/content/ContentResolver#requestSync(android.content.SyncRequest)) +made by foreground apps are special cased such that the resulting sync operations will be +exempted from app-standby throttling. + +### Two Levels of Exemption +Specifically, there are two different levels of exemption, depending on the state of the caller: +1. `ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET` +2. `ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP`, which is more powerful than 1. + +The exemption level is calculated in +[ContentService.getSyncExemptionAndCleanUpExtrasForCaller()](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/content/ContentService.java?q=%22int%20getSyncExemptionAndCleanUpExtrasForCaller%22&ss=android%2Fplatform%2Fsuperproject), +which was [implemented slightly differently](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/content/ContentService.java?q=%22int%20getSyncExemptionAndCleanUpExtrasForCaller%22&ss=android%2Fplatform%2Fsuperproject) +in Android 9, compared to Android 10 and later. + +The logic is as follows: +- When the caller's procstate is `PROCESS_STATE_TOP` or above, + meaning if the caller has a foreground activity, + `SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP` will be set. + +- Otherwise, when the caller's procstate is `PROCESS_STATE_IMPORTANT_FOREGROUND` or above, + e.g. when the caller has a foreground service, a service bound by the system of a specific kind, + `SYNC_EXEMPTION_PROMOTE_BUCKET` will be set. + +- Additionally, on Android 10 and later, when the caller is + "UID-active" (but the procstate is below `PROCESS_STATE_TOP`), + `SYNC_EXEMPTION_PROMOTE_BUCKET` will be set. + This is what happens when the app has just received a high-priority FCM, for example. + Temp-allowlist is also used in various other situations. + +### Behavior of Each Exemption + +The exemptions are tracked in `SyncOperation.syncExemptionFlag`. + +- Behavior of `SYNC_EXEMPTION_PROMOTE_BUCKET` + - This will add `JobInfo.FLAG_EXEMPT_FROM_APP_STANDBY` to the sync job. This makes the job + subject to "ACTIVE" app quota, so minimum deferral will be applied to it. + + - This also reports `AppStandbyController.reportExemptedSyncStart()`, so the package that owns + the sync adapter is temporarily put in the "ACTIVE" bucket for the + duration of `mExemptedSyncStartTimeoutMillis`, whose default is 10 minutes as of 2020-10-23. + + This will allow the app to access network, even if it has been in the `RARE` bucket + (in which case, the system cuts its network access). + + Note if the device is dozing or in battery saver, promoting to the "ACTIVE" bucket will still + _not_ give the app network access. + +- Behavior of `SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP` + - This gives all the perks given by `SYNC_EXEMPTION_PROMOTE_BUCKET`, plus puts the target app + in the temp-allowlist (by calling `DeviceIdleInternal.addPowerSaveTempWhitelistApp()`) + for the duration of `SyncManagerConstants.getKeyExemptionTempWhitelistDurationInSeconds()`, + whose default is 10 minutes. + + Temp-allowlist will grant the app network access even if the device is in doze or in battery + saver. + + (However, note that when the device is dozing, sync jobs will not run anyway.) + +### How Retries Are Handled + +- When a sync operation needs a retry, SyncManager creates a new operation (job) with a back-off + (in `SyncManager.maybeRescheduleSync()`). In this case, the new sync operation will inherit + `SyncOperation.syncExemptionFlag`, unless the number of retries (not counting the original sync + job) is equal to or greater than `SyncManagerConstants.getMaxRetriesWithAppStandbyExemption()`, + whose default is 5. + +### Special-handling of Pre-installed Packages + +- When a content provider is accessed, `AppStandbyController.reportContentProviderUsage()` is + triggered, which elevates the standby bucket of the associated sync adapters' packages to `ACTIVE` + for the duration of `mSyncAdapterTimeoutMillis`, whose default is 10 minutes, but _only for_ + pre-installed packages. This is to help pre-installed sync adapters, which often don't have UI, + sync properly. + +- Also, since Android 11, all the pre-installed apps with no activities will be kept in + the `ACTIVE` bucket, which greatly relaxes app-standby throttling. But they're still subject + to doze and battery saver. + +### Summary + +- When the device is dozing, no sync operations will be executed. + +- Normally, sync operations are subject to App-Standby, which throttles jobs owned by background + apps. Jobs owned by foreground apps are not affected. + +- A sync operation requested by a foreground activity will be executed immediately even if the + app owning the sync adapter is in RARE bucket, and the device is in battery saver. + +- A sync operation requested by a foreground service (or a "bound foreground" service) + will be executed immediately even if the app owning the sync adapter is in RARE bucket, + *unless* the device is in battery saver. + + Since Android 9 and later, the same thing will happen if the requester is temp-allowlisted (e.g. + when it has just received a "high-priority FCM"). + +- There are certain exemptions for pre-installed apps, but doze and battery saver will still + block their sync adapters.
\ No newline at end of file |