Loading core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java +42 −62 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ import android.app.backup.BackupHelper; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; import android.content.SyncStatusObserver; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.util.Log; Loading @@ -47,8 +45,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Helper for backing up account sync settings (whether or not a service should be synced). The Loading Loading @@ -270,6 +266,10 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { // yet won't be restored. if (currentAccounts.contains(account)) { restoreExistingAccountSyncSettingsFromJSON(accountJSON); } else { // TODO: // Stash the data to a file that the SyncManager can read from to restore // settings at a later date. } } } finally { Loading Loading @@ -300,6 +300,31 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { /** * Restore account sync settings using the given JSON. This function won't work if the account * doesn't exist yet. * This function will only be called during Setup Wizard, where we are guaranteed that there * are no active syncs. * There are 2 pieces of data to restore - * isSyncable (corresponds to {@link ContentResolver#getIsSyncable(Account, String)} * syncEnabled (corresponds to {@link ContentResolver#getSyncAutomatically(Account, String)} * <strong>The restore favours adapters that were enabled on the old device, and doesn't care * about adapters that were disabled.</strong> * * syncEnabled=true in restore data. * syncEnabled will be true on this device. isSyncable will be left as the default in order to * give the enabled adapter the chance to run an initialization sync. * * syncEnabled=false in restore data. * syncEnabled will be false on this device. isSyncable will be set to 2, unless it was 0 on the * old device in which case it will be set to 0 on this device. This is because isSyncable=0 is * a rare state and was probably set to 0 for good reason (historically isSyncable is a way by * which adapters control their own sync state independently of sync settings which is * toggleable by the user). * isSyncable=2 is a new isSyncable state we introduced specifically to allow adapters that are * disabled after a restore to run initialization logic when the adapter is later enabled. * See com.android.server.content.SyncStorageEngine#setSyncAutomatically * * The end result is that an adapter that the user had on will be turned on and get an * initialization sync, while an adapter that the user had off will be off until the user * enables it on this device at which point it will get an initialization sync. */ private void restoreExistingAccountSyncSettingsFromJSON(JSONObject accountJSON) throws JSONException { Loading @@ -307,71 +332,26 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { JSONArray authorities = accountJSON.getJSONArray(KEY_ACCOUNT_AUTHORITIES); String accountName = accountJSON.getString(KEY_ACCOUNT_NAME); String accountType = accountJSON.getString(KEY_ACCOUNT_TYPE); final Account account = new Account(accountName, accountType); for (int i = 0; i < authorities.length(); i++) { JSONObject authority = (JSONObject) authorities.get(i); final String authorityName = authority.getString(KEY_AUTHORITY_NAME); boolean syncEnabled = authority.getBoolean(KEY_AUTHORITY_SYNC_ENABLED); // Cancel any active syncs. if (ContentResolver.isSyncActive(account, authorityName)) { ContentResolver.cancelSync(account, authorityName); } boolean overwriteSync = true; Bundle initializationExtras = createSyncInitializationBundle(); int currentSyncState = ContentResolver.getIsSyncable(account, authorityName); if (currentSyncState < 0) { // Requesting a sync is an asynchronous operation, so we setup a countdown latch to // wait for it to finish. Initialization syncs are generally very brief and // shouldn't take too much time to finish. final CountDownLatch latch = new CountDownLatch(1); Object syncStatusObserverHandle = ContentResolver.addStatusChangeListener( ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, new SyncStatusObserver() { @Override public void onStatusChanged(int which) { if (!ContentResolver.isSyncActive(account, authorityName)) { latch.countDown(); } } }); boolean wasSyncEnabled = authority.getBoolean(KEY_AUTHORITY_SYNC_ENABLED); int wasSyncable = authority.getInt(KEY_AUTHORITY_SYNC_STATE); // If we set sync settings for a sync that hasn't been initialized yet, we run the // risk of having our changes overwritten later on when the sync gets initialized. // To prevent this from happening we will manually initiate the sync adapter. We // also explicitly pass in a Bundle with SYNC_EXTRAS_INITIALIZE to prevent a data // sync from running after the initialization sync. Two syncs will be scheduled, but // the second one (data sync) will override the first one (initialization sync) and // still behave as an initialization sync because of the Bundle. ContentResolver.requestSync(account, authorityName, initializationExtras); ContentResolver.setSyncAutomaticallyAsUser( account, authorityName, wasSyncEnabled, 0 /* user Id */); boolean done = false; try { done = latch.await(SYNC_REQUEST_LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS); } catch (InterruptedException e) { Log.e(TAG, "CountDownLatch interrupted\n" + e); done = false; } if (!done) { overwriteSync = false; Log.i(TAG, "CountDownLatch timed out, skipping '" + authorityName + "' authority."); if (!wasSyncEnabled) { ContentResolver.setIsSyncable( account, authorityName, wasSyncable == 0 ? 0 /* not syncable */ : 2 /* syncable but needs initialization */); } ContentResolver.removeStatusChangeListener(syncStatusObserverHandle); } if (overwriteSync) { ContentResolver.setSyncAutomatically(account, authorityName, syncEnabled); Log.i(TAG, "Set sync automatically for '" + authorityName + "': " + syncEnabled); } } } private Bundle createSyncInitializationBundle() { Bundle extras = new Bundle(); extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true); return extras; } @Override public void writeNewStateDescription(ParcelFileDescriptor newState) { Loading services/core/java/com/android/server/content/SyncManager.java +4 −3 Original line number Diff line number Diff line Loading @@ -801,7 +801,7 @@ public class SyncManager { for (String authority : syncableAuthorities) { int isSyncable = getIsSyncable(account.account, account.userId, authority); if (isSyncable == 0) { if (isSyncable == AuthorityInfo.NOT_SYNCABLE) { continue; } final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo; Loading @@ -813,8 +813,9 @@ public class SyncManager { final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs(); final boolean isAlwaysSyncable = syncAdapterInfo.type.isAlwaysSyncable(); if (isSyncable < 0 && isAlwaysSyncable) { mSyncStorageEngine.setIsSyncable(account.account, account.userId, authority, 1); isSyncable = 1; mSyncStorageEngine.setIsSyncable( account.account, account.userId, authority, AuthorityInfo.SYNCABLE); isSyncable = AuthorityInfo.SYNCABLE; } if (onlyThoseWithUnkownSyncableState && isSyncable >= 0) { continue; Loading services/core/java/com/android/server/content/SyncStorageEngine.java +54 −22 Original line number Diff line number Diff line Loading @@ -301,6 +301,30 @@ public class SyncStorageEngine extends Handler { } public static class AuthorityInfo { // Legal values of getIsSyncable /** * Default state for a newly installed adapter. An uninitialized adapter will receive an * initialization sync which are governed by a different set of rules to that of regular * syncs. */ public static final int NOT_INITIALIZED = -1; /** * The adapter will not receive any syncs. This is behaviourally equivalent to * setSyncAutomatically -> false. However setSyncAutomatically is surfaced to the user * while this is generally meant to be controlled by the developer. */ public static final int NOT_SYNCABLE = 0; /** * The adapter is initialized and functioning. This is the normal state for an adapter. */ public static final int SYNCABLE = 1; /** * The adapter is syncable but still requires an initialization sync. For example an adapter * than has been restored from a previous device will be in this state. Not meant for * external use. */ public static final int SYNCABLE_NOT_INITIALIZED = 2; final EndPoint target; final int ident; boolean enabled; Loading Loading @@ -349,12 +373,11 @@ public class SyncStorageEngine extends Handler { } private void defaultInitialisation() { syncable = -1; // default to "unknown" syncable = NOT_INITIALIZED; // 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 PeriodicSync defaultSync; // Old version is one sync a day. Empty bundle gets replaced by any addPeriodicSync() // call. // Old version is one sync a day. if (target.target_provider) { defaultSync = new PeriodicSync(target.account, target.provider, Loading Loading @@ -663,6 +686,12 @@ public class SyncStorageEngine extends Handler { } return; } // If the adapter was syncable but missing its initialization sync, set it to // uninitialized now. This is to give it a chance to run any one-time initialization // logic. if (sync && authority.syncable == AuthorityInfo.SYNCABLE_NOT_INITIALIZED) { authority.syncable = AuthorityInfo.NOT_INITIALIZED; } authority.enabled = sync; writeAccountInfoLocked(); } Loading @@ -682,7 +711,7 @@ public class SyncStorageEngine extends Handler { new EndPoint(account, providerName, userId), "get authority syncable"); if (authority == null) { return -1; return AuthorityInfo.NOT_INITIALIZED; } return authority.syncable; } Loading @@ -696,7 +725,7 @@ public class SyncStorageEngine extends Handler { return authorityInfo.syncable; } } return -1; return AuthorityInfo.NOT_INITIALIZED; } } Loading @@ -720,7 +749,8 @@ public class SyncStorageEngine extends Handler { } public void setIsTargetServiceActive(ComponentName cname, int userId, boolean active) { setSyncableStateForEndPoint(new EndPoint(cname, userId), active ? 1 : 0); setSyncableStateForEndPoint(new EndPoint(cname, userId), active ? AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE); } /** Loading @@ -733,10 +763,8 @@ public class SyncStorageEngine extends Handler { AuthorityInfo aInfo; synchronized (mAuthorities) { aInfo = getOrCreateAuthorityLocked(target, -1, false); if (syncable > 1) { syncable = 1; } else if (syncable < -1) { syncable = -1; if (syncable < AuthorityInfo.NOT_INITIALIZED) { syncable = AuthorityInfo.NOT_INITIALIZED; } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.d(TAG, "setIsSyncable: " + aInfo.toString() + " -> " + syncable); Loading @@ -750,7 +778,7 @@ public class SyncStorageEngine extends Handler { aInfo.syncable = syncable; writeAccountInfoLocked(); } if (syncable > 0) { if (syncable == AuthorityInfo.SYNCABLE) { requestSync(aInfo, SyncOperation.REASON_IS_SYNCABLE, new Bundle()); } reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS); Loading Loading @@ -2012,7 +2040,7 @@ public class SyncStorageEngine extends Handler { int userId = user == null ? 0 : Integer.parseInt(user); if (accountType == null && packageName == null) { accountType = "com.google"; syncable = "unknown"; syncable = String.valueOf(AuthorityInfo.NOT_INITIALIZED); } authority = mAuthorities.get(id); if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) { Loading Loading @@ -2052,11 +2080,19 @@ public class SyncStorageEngine extends Handler { } if (authority != null) { authority.enabled = enabled == null || Boolean.parseBoolean(enabled); try { authority.syncable = (syncable == null) ? AuthorityInfo.NOT_INITIALIZED : Integer.parseInt(syncable); } catch (NumberFormatException e) { // On L we stored this as {"unknown", "true", "false"} so fall back to this // format. if ("unknown".equals(syncable)) { authority.syncable = -1; authority.syncable = AuthorityInfo.NOT_INITIALIZED; } else { authority.syncable = (syncable == null || Boolean.parseBoolean(syncable)) ? 1 : 0; authority.syncable = Boolean.parseBoolean(syncable) ? AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE; } } } else { Log.w(TAG, "Failure adding authority: account=" Loading Loading @@ -2190,11 +2226,7 @@ public class SyncStorageEngine extends Handler { out.attribute(null, "package", info.service.getPackageName()); out.attribute(null, "class", info.service.getClassName()); } if (authority.syncable < 0) { out.attribute(null, "syncable", "unknown"); } else { out.attribute(null, "syncable", Boolean.toString(authority.syncable != 0)); } out.attribute(null, "syncable", Integer.toString(authority.syncable)); for (PeriodicSync periodicSync : authority.periodicSyncs) { out.startTag(null, "periodicSync"); out.attribute(null, "period", Long.toString(periodicSync.period)); Loading Loading
core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java +42 −62 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ import android.app.backup.BackupHelper; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; import android.content.SyncStatusObserver; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.util.Log; Loading @@ -47,8 +45,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Helper for backing up account sync settings (whether or not a service should be synced). The Loading Loading @@ -270,6 +266,10 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { // yet won't be restored. if (currentAccounts.contains(account)) { restoreExistingAccountSyncSettingsFromJSON(accountJSON); } else { // TODO: // Stash the data to a file that the SyncManager can read from to restore // settings at a later date. } } } finally { Loading Loading @@ -300,6 +300,31 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { /** * Restore account sync settings using the given JSON. This function won't work if the account * doesn't exist yet. * This function will only be called during Setup Wizard, where we are guaranteed that there * are no active syncs. * There are 2 pieces of data to restore - * isSyncable (corresponds to {@link ContentResolver#getIsSyncable(Account, String)} * syncEnabled (corresponds to {@link ContentResolver#getSyncAutomatically(Account, String)} * <strong>The restore favours adapters that were enabled on the old device, and doesn't care * about adapters that were disabled.</strong> * * syncEnabled=true in restore data. * syncEnabled will be true on this device. isSyncable will be left as the default in order to * give the enabled adapter the chance to run an initialization sync. * * syncEnabled=false in restore data. * syncEnabled will be false on this device. isSyncable will be set to 2, unless it was 0 on the * old device in which case it will be set to 0 on this device. This is because isSyncable=0 is * a rare state and was probably set to 0 for good reason (historically isSyncable is a way by * which adapters control their own sync state independently of sync settings which is * toggleable by the user). * isSyncable=2 is a new isSyncable state we introduced specifically to allow adapters that are * disabled after a restore to run initialization logic when the adapter is later enabled. * See com.android.server.content.SyncStorageEngine#setSyncAutomatically * * The end result is that an adapter that the user had on will be turned on and get an * initialization sync, while an adapter that the user had off will be off until the user * enables it on this device at which point it will get an initialization sync. */ private void restoreExistingAccountSyncSettingsFromJSON(JSONObject accountJSON) throws JSONException { Loading @@ -307,71 +332,26 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { JSONArray authorities = accountJSON.getJSONArray(KEY_ACCOUNT_AUTHORITIES); String accountName = accountJSON.getString(KEY_ACCOUNT_NAME); String accountType = accountJSON.getString(KEY_ACCOUNT_TYPE); final Account account = new Account(accountName, accountType); for (int i = 0; i < authorities.length(); i++) { JSONObject authority = (JSONObject) authorities.get(i); final String authorityName = authority.getString(KEY_AUTHORITY_NAME); boolean syncEnabled = authority.getBoolean(KEY_AUTHORITY_SYNC_ENABLED); // Cancel any active syncs. if (ContentResolver.isSyncActive(account, authorityName)) { ContentResolver.cancelSync(account, authorityName); } boolean overwriteSync = true; Bundle initializationExtras = createSyncInitializationBundle(); int currentSyncState = ContentResolver.getIsSyncable(account, authorityName); if (currentSyncState < 0) { // Requesting a sync is an asynchronous operation, so we setup a countdown latch to // wait for it to finish. Initialization syncs are generally very brief and // shouldn't take too much time to finish. final CountDownLatch latch = new CountDownLatch(1); Object syncStatusObserverHandle = ContentResolver.addStatusChangeListener( ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, new SyncStatusObserver() { @Override public void onStatusChanged(int which) { if (!ContentResolver.isSyncActive(account, authorityName)) { latch.countDown(); } } }); boolean wasSyncEnabled = authority.getBoolean(KEY_AUTHORITY_SYNC_ENABLED); int wasSyncable = authority.getInt(KEY_AUTHORITY_SYNC_STATE); // If we set sync settings for a sync that hasn't been initialized yet, we run the // risk of having our changes overwritten later on when the sync gets initialized. // To prevent this from happening we will manually initiate the sync adapter. We // also explicitly pass in a Bundle with SYNC_EXTRAS_INITIALIZE to prevent a data // sync from running after the initialization sync. Two syncs will be scheduled, but // the second one (data sync) will override the first one (initialization sync) and // still behave as an initialization sync because of the Bundle. ContentResolver.requestSync(account, authorityName, initializationExtras); ContentResolver.setSyncAutomaticallyAsUser( account, authorityName, wasSyncEnabled, 0 /* user Id */); boolean done = false; try { done = latch.await(SYNC_REQUEST_LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS); } catch (InterruptedException e) { Log.e(TAG, "CountDownLatch interrupted\n" + e); done = false; } if (!done) { overwriteSync = false; Log.i(TAG, "CountDownLatch timed out, skipping '" + authorityName + "' authority."); if (!wasSyncEnabled) { ContentResolver.setIsSyncable( account, authorityName, wasSyncable == 0 ? 0 /* not syncable */ : 2 /* syncable but needs initialization */); } ContentResolver.removeStatusChangeListener(syncStatusObserverHandle); } if (overwriteSync) { ContentResolver.setSyncAutomatically(account, authorityName, syncEnabled); Log.i(TAG, "Set sync automatically for '" + authorityName + "': " + syncEnabled); } } } private Bundle createSyncInitializationBundle() { Bundle extras = new Bundle(); extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true); return extras; } @Override public void writeNewStateDescription(ParcelFileDescriptor newState) { Loading
services/core/java/com/android/server/content/SyncManager.java +4 −3 Original line number Diff line number Diff line Loading @@ -801,7 +801,7 @@ public class SyncManager { for (String authority : syncableAuthorities) { int isSyncable = getIsSyncable(account.account, account.userId, authority); if (isSyncable == 0) { if (isSyncable == AuthorityInfo.NOT_SYNCABLE) { continue; } final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo; Loading @@ -813,8 +813,9 @@ public class SyncManager { final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs(); final boolean isAlwaysSyncable = syncAdapterInfo.type.isAlwaysSyncable(); if (isSyncable < 0 && isAlwaysSyncable) { mSyncStorageEngine.setIsSyncable(account.account, account.userId, authority, 1); isSyncable = 1; mSyncStorageEngine.setIsSyncable( account.account, account.userId, authority, AuthorityInfo.SYNCABLE); isSyncable = AuthorityInfo.SYNCABLE; } if (onlyThoseWithUnkownSyncableState && isSyncable >= 0) { continue; Loading
services/core/java/com/android/server/content/SyncStorageEngine.java +54 −22 Original line number Diff line number Diff line Loading @@ -301,6 +301,30 @@ public class SyncStorageEngine extends Handler { } public static class AuthorityInfo { // Legal values of getIsSyncable /** * Default state for a newly installed adapter. An uninitialized adapter will receive an * initialization sync which are governed by a different set of rules to that of regular * syncs. */ public static final int NOT_INITIALIZED = -1; /** * The adapter will not receive any syncs. This is behaviourally equivalent to * setSyncAutomatically -> false. However setSyncAutomatically is surfaced to the user * while this is generally meant to be controlled by the developer. */ public static final int NOT_SYNCABLE = 0; /** * The adapter is initialized and functioning. This is the normal state for an adapter. */ public static final int SYNCABLE = 1; /** * The adapter is syncable but still requires an initialization sync. For example an adapter * than has been restored from a previous device will be in this state. Not meant for * external use. */ public static final int SYNCABLE_NOT_INITIALIZED = 2; final EndPoint target; final int ident; boolean enabled; Loading Loading @@ -349,12 +373,11 @@ public class SyncStorageEngine extends Handler { } private void defaultInitialisation() { syncable = -1; // default to "unknown" syncable = NOT_INITIALIZED; // 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 PeriodicSync defaultSync; // Old version is one sync a day. Empty bundle gets replaced by any addPeriodicSync() // call. // Old version is one sync a day. if (target.target_provider) { defaultSync = new PeriodicSync(target.account, target.provider, Loading Loading @@ -663,6 +686,12 @@ public class SyncStorageEngine extends Handler { } return; } // If the adapter was syncable but missing its initialization sync, set it to // uninitialized now. This is to give it a chance to run any one-time initialization // logic. if (sync && authority.syncable == AuthorityInfo.SYNCABLE_NOT_INITIALIZED) { authority.syncable = AuthorityInfo.NOT_INITIALIZED; } authority.enabled = sync; writeAccountInfoLocked(); } Loading @@ -682,7 +711,7 @@ public class SyncStorageEngine extends Handler { new EndPoint(account, providerName, userId), "get authority syncable"); if (authority == null) { return -1; return AuthorityInfo.NOT_INITIALIZED; } return authority.syncable; } Loading @@ -696,7 +725,7 @@ public class SyncStorageEngine extends Handler { return authorityInfo.syncable; } } return -1; return AuthorityInfo.NOT_INITIALIZED; } } Loading @@ -720,7 +749,8 @@ public class SyncStorageEngine extends Handler { } public void setIsTargetServiceActive(ComponentName cname, int userId, boolean active) { setSyncableStateForEndPoint(new EndPoint(cname, userId), active ? 1 : 0); setSyncableStateForEndPoint(new EndPoint(cname, userId), active ? AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE); } /** Loading @@ -733,10 +763,8 @@ public class SyncStorageEngine extends Handler { AuthorityInfo aInfo; synchronized (mAuthorities) { aInfo = getOrCreateAuthorityLocked(target, -1, false); if (syncable > 1) { syncable = 1; } else if (syncable < -1) { syncable = -1; if (syncable < AuthorityInfo.NOT_INITIALIZED) { syncable = AuthorityInfo.NOT_INITIALIZED; } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.d(TAG, "setIsSyncable: " + aInfo.toString() + " -> " + syncable); Loading @@ -750,7 +778,7 @@ public class SyncStorageEngine extends Handler { aInfo.syncable = syncable; writeAccountInfoLocked(); } if (syncable > 0) { if (syncable == AuthorityInfo.SYNCABLE) { requestSync(aInfo, SyncOperation.REASON_IS_SYNCABLE, new Bundle()); } reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS); Loading Loading @@ -2012,7 +2040,7 @@ public class SyncStorageEngine extends Handler { int userId = user == null ? 0 : Integer.parseInt(user); if (accountType == null && packageName == null) { accountType = "com.google"; syncable = "unknown"; syncable = String.valueOf(AuthorityInfo.NOT_INITIALIZED); } authority = mAuthorities.get(id); if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) { Loading Loading @@ -2052,11 +2080,19 @@ public class SyncStorageEngine extends Handler { } if (authority != null) { authority.enabled = enabled == null || Boolean.parseBoolean(enabled); try { authority.syncable = (syncable == null) ? AuthorityInfo.NOT_INITIALIZED : Integer.parseInt(syncable); } catch (NumberFormatException e) { // On L we stored this as {"unknown", "true", "false"} so fall back to this // format. if ("unknown".equals(syncable)) { authority.syncable = -1; authority.syncable = AuthorityInfo.NOT_INITIALIZED; } else { authority.syncable = (syncable == null || Boolean.parseBoolean(syncable)) ? 1 : 0; authority.syncable = Boolean.parseBoolean(syncable) ? AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE; } } } else { Log.w(TAG, "Failure adding authority: account=" Loading Loading @@ -2190,11 +2226,7 @@ public class SyncStorageEngine extends Handler { out.attribute(null, "package", info.service.getPackageName()); out.attribute(null, "class", info.service.getClassName()); } if (authority.syncable < 0) { out.attribute(null, "syncable", "unknown"); } else { out.attribute(null, "syncable", Boolean.toString(authority.syncable != 0)); } out.attribute(null, "syncable", Integer.toString(authority.syncable)); for (PeriodicSync periodicSync : authority.periodicSyncs) { out.startTag(null, "periodicSync"); out.attribute(null, "period", Long.toString(periodicSync.period)); Loading