App Standby Buckets - What are the restrictions on the "Never" bucket (bucket 50)

1.2k views Asked by At

The Android documentation mentions the restrictions the OS imposes on apps for each of the following buckets: "active", "working set", "frequent", and "rare".

The only documentation I found for the "never" bucket (the bucket that apps that were never launched start in) mentiones:

In addition, there's a special never bucket for apps that have been installed but have never been run. The system imposes severe restrictions on these apps.

Does anyone know what restrictions the OS imposes on apps in the "never" bucket? (bucket 50)

1

There are 1 answers

0
OmB On

First a little disclaimer about my answer: My answer is based on the AOSP code, and may be changed across versions or manufacturers.

Moreover, we can perhaps infer that manufacturers has a say on how it behaves:

Every manufacturer can set their own criteria for how non-active apps are assigned to buckets. You should not try to influence which bucket your app is assigned to. Instead, focus on making sure your app behaves well in whatever bucket it might be in. Your app can find out what bucket it's currently in by calling the new method UsageStatsManager.getAppStandbyBucket().

Jobs will not run (with or without a charger)

If you'll look at QuotaController which is where buckets restrictions for job is implemented: frameworks/base/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java

You'll see that NEVER_INDEX just shut down the job availability, and will not implicitly proceed/upgrade it self to a better bucket unless something will explicitly changes the bucket (for example, launching activity). This applies also when the charger is connected as you can see at isWithinQuotaLocked():

if (standbyBucket == NEVER_INDEX) return false;

    // Quota constraint is not enforced while charging.
    if (mChargeTracker.isCharging()) {
        // Restricted jobs require additional constraints when charging, so don't immediately
        // mark quota as free when charging.
        if (standbyBucket != RESTRICTED_INDEX) {
            return true;
        }

Alarms will not run (with or without a charger)

look at AlarmManagerService: frameworks/base/services/core/java/com/android/server/AlarmManagerService.java

There, you can see that reorderAlarmsBasedOnStandbyBuckets() is called when the charger is connected/disconnected.

It reorders the alarms based on the quotas and for bucket never it is 0.

private final int[] DEFAULT_APP_STANDBY_QUOTAS = {
                720,    // Active
                10,     // Working
                2,      // Frequent
                1,      // Rare
                0       // Never
        };

The code is deffering it for a day until it becomes more than a 0:

      if (quotaForBucket <= 0) {
         // Just keep deferring for a day till the quota changes
          minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY;
      }

Network will not work on background

Because there are no jobs and alarms available, there's no endpoint where you can use the network.

It will start working only when foreground service/ activity will change the standby bucket to active as written in the doc:

An app is in the active bucket if the user is currently using the app or very recently used the app. For example: • The app has launched an activity • The app is running a foreground service • The app has a sync adapter associated with a content provider used by a foreground app • The user clicks on a notification from the app