mobile/android/base/fxa/sync/FxAccountSchedulePolicy.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko.fxa.sync;
     7 import org.mozilla.gecko.background.common.log.Logger;
     8 import org.mozilla.gecko.db.BrowserContract;
     9 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
    10 import org.mozilla.gecko.fxa.login.State.Action;
    11 import org.mozilla.gecko.sync.BackoffHandler;
    13 import android.accounts.Account;
    14 import android.content.ContentResolver;
    15 import android.content.Context;
    16 import android.os.Bundle;
    18 public class FxAccountSchedulePolicy implements SchedulePolicy {
    19   private static final String LOG_TAG = "FxAccountSchedulePolicy";
    21   // Our poll intervals are used to trigger automatic background syncs
    22   // in the absence of user activity.
    23   //
    24   // We also receive sync requests as a result of network tickles, so
    25   // these intervals are long, with the exception of the rapid polling
    26   // while we wait for verification: if we're waiting for the user to
    27   // click on a verification link, we sync very often in order to detect
    28   // a change in state.
    29   //
    30   // In the case of unverified -> unverified (no transition), this should be
    31   // very close to a single HTTP request (with the SyncAdapter overhead, of
    32   // course, but that's not wildly different from alarm manager overhead).
    33   //
    34   // The /account/status endpoint is HAWK authed by sessionToken, so we still
    35   // have to do some crypto no matter what.
    37   // TODO: only do this for a while...
    38   public static final long POLL_INTERVAL_PENDING_VERIFICATION = 60;         // 1 minute.
    40   // If we're in some kind of error state, there's no point trying often.
    41   // This is not the same as a server-imposed backoff, which will be
    42   // reflected dynamically.
    43   public static final long POLL_INTERVAL_ERROR_STATE_SEC = 24 * 60 * 60;    // 24 hours.
    45   // If we're the only device, just sync once or twice a day in case that
    46   // changes.
    47   public static final long POLL_INTERVAL_SINGLE_DEVICE_SEC = 18 * 60 * 60;  // 18 hours.
    49   // And if we know there are other devices, let's sync often enough that
    50   // we'll be more likely to be caught up (even if not completely) by the
    51   // time you next use this device. This is also achieved via Android's
    52   // network tickles.
    53   public static final long POLL_INTERVAL_MULTI_DEVICE_SEC = 12 * 60 * 60;   // 12 hours.
    55   // This is used solely as an optimization for backoff handling, so it's not
    56   // persisted.
    57   private static volatile long POLL_INTERVAL_CURRENT_SEC = POLL_INTERVAL_SINGLE_DEVICE_SEC;
    59   // Never sync more frequently than this, unless forced.
    60   // This is to avoid overly-frequent syncs during active browsing.
    61   public static final long RATE_LIMIT_FUNDAMENTAL_SEC = 90;                 // 90 seconds.
    63   /**
    64    * We are prompted to sync by several inputs:
    65    * * Periodic syncs that we schedule at long intervals. See the POLL constants.
    66    * * Network-tickle-based syncs that Android starts.
    67    * * Upload-only syncs that are caused by local database writes.
    68    *
    69    * We rate-limit periodic and network-sourced events with this constant.
    70    * We rate limit <b>both</b> with {@link FxAccountSchedulePolicy#RATE_LIMIT_FUNDAMENTAL_SEC}.
    71    */
    72   public static final long RATE_LIMIT_BACKGROUND_SEC = 60 * 60;             // 1 hour.
    74   private final AndroidFxAccount account;
    75   private final Context context;
    77   public FxAccountSchedulePolicy(Context context, AndroidFxAccount account) {
    78     this.account = account;
    79     this.context = context;
    80   }
    82   /**
    83    * Return a millisecond timestamp in the future, offset from the current
    84    * time by the provided amount.
    85    * @param millis the duration by which to delay
    86    * @return a timestamp.
    87    */
    88   private static long delay(long millis) {
    89     return System.currentTimeMillis() + millis;
    90   }
    92   /**
    93    * Updates the existing system periodic sync interval to the specified duration.
    94    *
    95    * @param intervalSeconds the requested period, which Android will vary by up to 4%.
    96    */
    97   protected void requestPeriodicSync(final long intervalSeconds) {
    98     final String authority = BrowserContract.AUTHORITY;
    99     final Account account = this.account.getAndroidAccount();
   100     this.context.getContentResolver();
   101     Logger.info(LOG_TAG, "Scheduling periodic sync for " + intervalSeconds + ".");
   102     ContentResolver.addPeriodicSync(account, authority, Bundle.EMPTY, intervalSeconds);
   103     POLL_INTERVAL_CURRENT_SEC = intervalSeconds;
   104   }
   106   @Override
   107   public void onSuccessfulSync(int otherClientsCount) {
   108     // This undoes the change made in observeBackoffMillis -- once we hit backoff we'll
   109     // periodically sync at the backoff duration, but as soon as we succeed we'll switch
   110     // into the client-count-dependent interval.
   111     long interval = (otherClientsCount > 0) ? POLL_INTERVAL_MULTI_DEVICE_SEC : POLL_INTERVAL_SINGLE_DEVICE_SEC;
   112     requestPeriodicSync(interval);
   113   }
   115   @Override
   116   public void onHandleFinal(Action needed) {
   117     switch (needed) {
   118     case NeedsPassword:
   119     case NeedsUpgrade:
   120       requestPeriodicSync(POLL_INTERVAL_ERROR_STATE_SEC);
   121       break;
   122     case NeedsVerification:
   123       requestPeriodicSync(POLL_INTERVAL_PENDING_VERIFICATION);
   124       break;
   125     case None:
   126       // No action needed: we'll set the periodic sync interval
   127       // when the sync finishes, via the SessionCallback.
   128       break;
   129     }
   130   }
   132   @Override
   133   public void onUpgradeRequired() {
   134     // TODO: this shouldn't occur in FxA, but when we upgrade we
   135     // need to reduce the interval again.
   136     requestPeriodicSync(POLL_INTERVAL_ERROR_STATE_SEC);
   137   }
   139   @Override
   140   public void onUnauthorized() {
   141     // TODO: this shouldn't occur in FxA, but when we fix our credentials
   142     // we need to reduce the interval again.
   143     requestPeriodicSync(POLL_INTERVAL_ERROR_STATE_SEC);
   144   }
   146   @Override
   147   public void configureBackoffMillisOnBackoff(BackoffHandler backoffHandler, long backoffMillis, boolean onlyExtend) {
   148     if (onlyExtend) {
   149       backoffHandler.extendEarliestNextRequest(delay(backoffMillis));
   150     } else {
   151       backoffHandler.setEarliestNextRequest(delay(backoffMillis));
   152     }
   154     // Yes, we might be part-way through the interval, in which case the backoff
   155     // code will do its job. But we certainly don't want to reduce the interval
   156     // if we're given a small backoff instruction.
   157     // We'll reset the poll interval next time we sync without a backoff instruction.
   158     if (backoffMillis > (POLL_INTERVAL_CURRENT_SEC * 1000)) {
   159       // Slightly inflate the backoff duration to ensure that a fuzzed
   160       // periodic sync doesn't occur before our backoff has passed. Android
   161       // 19+ default to a 4% fuzz factor.
   162       requestPeriodicSync((long) Math.ceil((1.05 * backoffMillis) / 1000));
   163     }
   164   }
   166   /**
   167    * Accepts two {@link BackoffHandler} instances as input. These are used
   168    * respectively to track fundamental rate limiting, and to separately
   169    * rate-limit periodic and network-tickled syncs.
   170    */
   171   @Override
   172   public void configureBackoffMillisBeforeSyncing(BackoffHandler fundamentalRateHandler, BackoffHandler backgroundRateHandler) {
   173     fundamentalRateHandler.setEarliestNextRequest(delay(RATE_LIMIT_FUNDAMENTAL_SEC * 1000));
   174     backgroundRateHandler.setEarliestNextRequest(delay(RATE_LIMIT_BACKGROUND_SEC * 1000));
   175   }
   176 }

mercurial