summaryrefslogtreecommitdiffstats
path: root/core/java/android/content/SyncStorageEngine.java
diff options
context:
space:
mode:
authorFred Quintana <fredq@google.com>2010-01-21 14:24:20 -0800
committerFred Quintana <fredq@google.com>2010-01-25 16:41:58 -0800
commit307da1a46b4c9b711bafe8fbaaa6b98e8868c18e (patch)
treea83cd290b7fc4e6d7f11a56c96318f282df37838 /core/java/android/content/SyncStorageEngine.java
parente0560e484b4b31edbb81beae1dca7e109126cb73 (diff)
downloadframeworks_base-307da1a46b4c9b711bafe8fbaaa6b98e8868c18e.zip
frameworks_base-307da1a46b4c9b711bafe8fbaaa6b98e8868c18e.tar.gz
frameworks_base-307da1a46b4c9b711bafe8fbaaa6b98e8868c18e.tar.bz2
enhance the sync manager backoff logic and add support for retry-after
moved SyncQueue and SyncOperation into their own top-level classes to ease maintainability and testing6 removed some dead code
Diffstat (limited to 'core/java/android/content/SyncStorageEngine.java')
-rw-r--r--core/java/android/content/SyncStorageEngine.java120
1 files changed, 108 insertions, 12 deletions
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 4c53201..db70096 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -36,10 +36,11 @@ import android.os.Message;
import android.os.Parcel;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.SystemProperties;
+import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;
+import android.util.Pair;
import java.io.File;
import java.io.FileInputStream;
@@ -88,6 +89,8 @@ public class SyncStorageEngine extends Handler {
/** Enum value for a user-initiated sync. */
public static final int SOURCE_USER = 3;
+ public static final long NOT_IN_BACKOFF_MODE = -1;
+
private static final Intent SYNC_CONNECTION_SETTING_CHANGED_INTENT =
new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
@@ -117,16 +120,18 @@ public class SyncStorageEngine extends Handler {
final int syncSource;
final String authority;
final Bundle extras; // note: read-only.
+ final boolean expedited;
int authorityId;
byte[] flatExtras;
PendingOperation(Account account, int source,
- String authority, Bundle extras) {
+ String authority, Bundle extras, boolean expedited) {
this.account = account;
this.syncSource = source;
this.authority = authority;
this.extras = extras != null ? new Bundle(extras) : extras;
+ this.expedited = expedited;
this.authorityId = -1;
}
@@ -136,6 +141,7 @@ public class SyncStorageEngine extends Handler {
this.authority = other.authority;
this.extras = other.extras;
this.authorityId = other.authorityId;
+ this.expedited = other.expedited;
}
}
@@ -155,6 +161,9 @@ public class SyncStorageEngine extends Handler {
final int ident;
boolean enabled;
int syncable;
+ long backoffTime;
+ long backoffDelay;
+ long delayUntil;
AuthorityInfo(Account account, String authority, int ident) {
this.account = account;
@@ -162,6 +171,8 @@ public class SyncStorageEngine extends Handler {
this.ident = ident;
enabled = SYNC_ENABLED_DEFAULT;
syncable = -1; // default to "unknown"
+ backoffTime = -1; // if < 0 then we aren't in backoff mode
+ backoffDelay = -1; // if < 0 then we aren't in backoff mode
}
}
@@ -280,7 +291,7 @@ public class SyncStorageEngine extends Handler {
public static void init(Context context) {
if (sSyncStorageEngine != null) {
- throw new IllegalStateException("already initialized");
+ return;
}
sSyncStorageEngine = new SyncStorageEngine(context);
}
@@ -380,7 +391,7 @@ public class SyncStorageEngine extends Handler {
}
if (!wasEnabled && sync) {
- mContext.getContentResolver().requestSync(account, providerName, new Bundle());
+ ContentResolver.requestSync(account, providerName, new Bundle());
}
reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
}
@@ -424,11 +435,91 @@ public class SyncStorageEngine extends Handler {
}
if (oldState <= 0 && syncable > 0) {
- mContext.getContentResolver().requestSync(account, providerName, new Bundle());
+ ContentResolver.requestSync(account, providerName, new Bundle());
}
reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
}
+ public Pair<Long, Long> getBackoff(Account account, String providerName) {
+ synchronized (mAuthorities) {
+ AuthorityInfo authority = getAuthorityLocked(account, providerName, "getBackoff");
+ if (authority == null || authority.backoffTime < 0) {
+ return null;
+ }
+ return Pair.create(authority.backoffTime, authority.backoffDelay);
+ }
+ }
+
+ public void setBackoff(Account account, String providerName,
+ long nextSyncTime, long nextDelay) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "setBackoff: " + account + ", provider " + providerName
+ + " -> nextSyncTime " + nextSyncTime + ", nextDelay " + nextDelay);
+ }
+ boolean changed = false;
+ synchronized (mAuthorities) {
+ if (account == null || providerName == null) {
+ for (AccountInfo accountInfo : mAccounts.values()) {
+ if (account != null && !account.equals(accountInfo.account)) continue;
+ for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
+ if (providerName != null && !providerName.equals(authorityInfo.authority)) {
+ continue;
+ }
+ if (authorityInfo.backoffTime != nextSyncTime
+ || authorityInfo.backoffDelay != nextDelay) {
+ authorityInfo.backoffTime = nextSyncTime;
+ authorityInfo.backoffDelay = nextDelay;
+ changed = true;
+ }
+ }
+ }
+ } else {
+ AuthorityInfo authority =
+ getOrCreateAuthorityLocked(account, providerName, -1, false);
+ if (authority.backoffTime == nextSyncTime && authority.backoffDelay == nextDelay) {
+ return;
+ }
+ authority.backoffTime = nextSyncTime;
+ authority.backoffDelay = nextDelay;
+ changed = true;
+ }
+ if (changed) {
+ writeAccountInfoLocked();
+ }
+ }
+
+ if (changed) {
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ }
+ }
+
+ public void setDelayUntilTime(Account account, String providerName, long delayUntil) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "setDelayUntil: " + account + ", provider " + providerName
+ + " -> delayUntil " + delayUntil);
+ }
+ synchronized (mAuthorities) {
+ AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
+ if (authority.delayUntil == delayUntil) {
+ return;
+ }
+ authority.delayUntil = delayUntil;
+ writeAccountInfoLocked();
+ }
+
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ }
+
+ public long getDelayUntilTime(Account account, String providerName) {
+ synchronized (mAuthorities) {
+ AuthorityInfo authority = getAuthorityLocked(account, providerName, "getDelayUntil");
+ if (authority == null) {
+ return 0;
+ }
+ return authority.delayUntil;
+ }
+ }
+
public void setMasterSyncAutomatically(boolean flag) {
boolean old;
synchronized (mAuthorities) {
@@ -437,7 +528,7 @@ public class SyncStorageEngine extends Handler {
writeAccountInfoLocked();
}
if (!old && flag) {
- mContext.getContentResolver().requestSync(null, null, new Bundle());
+ ContentResolver.requestSync(null, null, new Bundle());
}
reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
mContext.sendBroadcast(SYNC_CONNECTION_SETTING_CHANGED_INTENT);
@@ -512,9 +603,6 @@ public class SyncStorageEngine extends Handler {
SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
status.pending = true;
- status.initialize = op.extras != null &&
- op.extras.containsKey(ContentResolver.SYNC_EXTRAS_INITIALIZE) &&
- op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE);
}
reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
@@ -1414,7 +1502,7 @@ public class SyncStorageEngine extends Handler {
}
}
- public static final int PENDING_OPERATION_VERSION = 1;
+ public static final int PENDING_OPERATION_VERSION = 2;
/**
* Read all pending operations back in to the initial engine state.
@@ -1429,7 +1517,7 @@ public class SyncStorageEngine extends Handler {
final int SIZE = in.dataSize();
while (in.dataPosition() < SIZE) {
int version = in.readInt();
- if (version != PENDING_OPERATION_VERSION) {
+ if (version != PENDING_OPERATION_VERSION && version != 1) {
Log.w(TAG, "Unknown pending operation version "
+ version + "; dropping all ops");
break;
@@ -1437,6 +1525,12 @@ public class SyncStorageEngine extends Handler {
int authorityId = in.readInt();
int syncSource = in.readInt();
byte[] flatExtras = in.createByteArray();
+ boolean expedited;
+ if (version == PENDING_OPERATION_VERSION) {
+ expedited = in.readInt() != 0;
+ } else {
+ expedited = false;
+ }
AuthorityInfo authority = mAuthorities.get(authorityId);
if (authority != null) {
Bundle extras = null;
@@ -1445,12 +1539,13 @@ public class SyncStorageEngine extends Handler {
}
PendingOperation op = new PendingOperation(
authority.account, syncSource,
- authority.authority, extras);
+ authority.authority, extras, expedited);
op.authorityId = authorityId;
op.flatExtras = flatExtras;
if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
+ " auth=" + op.authority
+ " src=" + op.syncSource
+ + " expedited=" + op.expedited
+ " extras=" + op.extras);
mPendingOperations.add(op);
}
@@ -1468,6 +1563,7 @@ public class SyncStorageEngine extends Handler {
op.flatExtras = flattenBundle(op.extras);
}
out.writeByteArray(op.flatExtras);
+ out.writeInt(op.expedited ? 1 : 0);
}
/**