Clear all pending backoffs on a reconnect event

Change-Id: I509e2c6c9d95922d196ac805eded523b674ad805
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index e07dbb8..599429b 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -17,7 +17,6 @@
 package android.content;
 
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -246,6 +245,7 @@
                 Log.v(TAG, "received connectivity action.  network info: " + networkInfo);
             }
 
+            final boolean wasConnected = mDataConnectionIsConnected;
             // only pay attention to the CONNECTED and DISCONNECTED states.
             // if connected, we are connected.
             // if disconnected, we may not be connected.  in some cases, we may be connected on
@@ -259,16 +259,19 @@
                     mDataConnectionIsConnected = true;
                     break;
                 case DISCONNECTED:
-                    if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
-                        mDataConnectionIsConnected = false;
-                    } else {
-                        mDataConnectionIsConnected = true;
-                    }
+                    mDataConnectionIsConnected = !intent.getBooleanExtra(
+                            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
                     break;
                 default:
                     // ignore the rest of the states -- leave our boolean alone.
             }
             if (mDataConnectionIsConnected) {
+                if (!wasConnected) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "Reconnection detected: clearing all backoffs");
+                    }
+                    mSyncStorageEngine.clearAllBackoffs();
+                }
                 sendCheckAlarmsMessage();
             }
         }
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 4a4edd2..c8ca6189 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -525,6 +525,33 @@
         }
     }
 
+    public void clearAllBackoffs() {
+        boolean changed = false;
+        synchronized (mAuthorities) {
+            for (AccountInfo accountInfo : mAccounts.values()) {
+                for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
+                    if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
+                            || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.v(TAG, "clearAllBackoffs:"
+                                    + " authority:" + authorityInfo.authority
+                                    + " account:" + accountInfo.account.name
+                                    + " backoffTime was: " + authorityInfo.backoffTime
+                                    + " backoffDelay was: " + authorityInfo.backoffDelay);
+                        }
+                        authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
+                        authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
+                        changed = true;
+                    }
+                }
+            }
+        }
+
+        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