diff options
author | Fred Quintana <fredq@google.com> | 2010-03-15 16:10:44 -0700 |
---|---|---|
committer | Fred Quintana <fredq@google.com> | 2010-03-16 10:01:54 -0700 |
commit | c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffc (patch) | |
tree | 9e2dabf9dde89a18360c5d4ce08a2e9648e3284f /core | |
parent | 74d4843641ca1f810e27989873697cba1f41338a (diff) | |
download | frameworks_base-c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffc.zip frameworks_base-c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffc.tar.gz frameworks_base-c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffc.tar.bz2 |
- make the SyncManager add periodic syncs when it upgrades from a
version of the accounts.xml file that pre-dated periodic syncs,
e.g. eclair or early froyo. http://b/2515823
- make the AccountManagerService dump() use a getAccounts call that
doesn't check the GET_ACCOUNTS permission to make it useful
in "adb bugreport"
- add some logging to SyncManager to help track down a problem
Change-Id: Icb646909074e2d327d71f6bb39cf06b6fac29e77
Diffstat (limited to 'core')
4 files changed, 150 insertions, 9 deletions
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 6d0a266..16b603c 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1699,7 +1699,7 @@ public class AccountManagerService } } } else { - Account[] accounts = getAccounts(null /* type */); + Account[] accounts = getAccountsByType(null /* type */); fout.println("Accounts: " + accounts.length); for (Account account : accounts) { fout.println(" " + account); diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 85769a6..840a714 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -416,6 +416,9 @@ public class SyncManager implements OnAccountsUpdateListener { } private void initializeSyncAdapter(Account account, String authority) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "initializeSyncAdapter: " + account + ", authority " + authority); + } SyncAdapterType syncAdapterType = SyncAdapterType.newKey(authority, account.type); RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType); @@ -427,9 +430,11 @@ public class SyncManager implements OnAccountsUpdateListener { Intent intent = new Intent(); intent.setAction("android.content.SyncAdapter"); intent.setComponent(syncAdapterInfo.componentName); - mContext.bindService(intent, new InitializerServiceConnection(account, authority, mContext, + if (!mContext.bindService(intent, new InitializerServiceConnection(account, authority, mContext, mMainHandler), - Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND); + Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND)) { + Log.w(TAG, "initializeSyncAdapter: failed to bind to " + intent); + } } private static class InitializerServiceConnection implements ServiceConnection { @@ -452,6 +457,9 @@ public class SyncManager implements OnAccountsUpdateListener { try { if (!mInitialized) { mInitialized = true; + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "calling initialize: " + mAccount + ", authority " + mAuthority); + } ISyncAdapter.Stub.asInterface(service).initialize(mAccount, mAuthority); } } catch (RemoteException e) { @@ -1307,7 +1315,6 @@ public class SyncManager implements OnAccountsUpdateListener { // it if sync is still failing private boolean mErrorNotificationInstalled = false; private volatile CountDownLatch mReadyToRunLatch = new CountDownLatch(1); - public void onBootCompleted() { mBootCompleted = true; if (mReadyToRunLatch != null) { diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 240da72..0ec2453 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -121,6 +121,9 @@ public class SyncStorageEngine extends Handler { private static final boolean SYNC_ENABLED_DEFAULT = false; + // the version of the accounts xml file format + private static final int ACCOUNTS_VERSION = 1; + public static class PendingOperation { final Account account; final int syncSource; @@ -1322,6 +1325,7 @@ public class SyncStorageEngine extends Handler { * Read all account information back in to the initial engine state. */ private void readAccountInfoLocked() { + boolean writeNeeded = false; FileInputStream fis = null; try { fis = mAccountInfoFile.openRead(); @@ -1336,6 +1340,16 @@ public class SyncStorageEngine extends Handler { if ("accounts".equals(tagName)) { String listen = parser.getAttributeValue( null, "listen-for-tickles"); + String versionString = parser.getAttributeValue(null, "version"); + int version; + try { + version = (versionString == null) ? 0 : Integer.parseInt(versionString); + } catch (NumberFormatException e) { + version = 0; + } + if (version < ACCOUNTS_VERSION) { + writeNeeded = true; + } mMasterSyncAutomatically = listen == null || Boolean.parseBoolean(listen); eventType = parser.next(); @@ -1346,7 +1360,7 @@ public class SyncStorageEngine extends Handler { tagName = parser.getName(); if (parser.getDepth() == 2) { if ("authority".equals(tagName)) { - authority = parseAuthority(parser); + authority = parseAuthority(parser, version); periodicSync = null; } } else if (parser.getDepth() == 3) { @@ -1364,9 +1378,11 @@ public class SyncStorageEngine extends Handler { } } catch (XmlPullParserException e) { Log.w(TAG, "Error reading accounts", e); + return; } catch (java.io.IOException e) { if (fis == null) Log.i(TAG, "No initial accounts"); else Log.w(TAG, "Error reading accounts", e); + return; } finally { if (fis != null) { try { @@ -1375,9 +1391,13 @@ public class SyncStorageEngine extends Handler { } } } + + if (writeNeeded) { + writeAccountInfoLocked(); + } } - private AuthorityInfo parseAuthority(XmlPullParser parser) { + private AuthorityInfo parseAuthority(XmlPullParser parser, int version) { AuthorityInfo authority = null; int id = -1; try { @@ -1406,8 +1426,14 @@ public class SyncStorageEngine extends Handler { if (DEBUG_FILE) Log.v(TAG, "Creating entry"); authority = getOrCreateAuthorityLocked( new Account(accountName, accountType), authorityName, id, false); - // clear this since we will read these later on - authority.periodicSyncs.clear(); + // If the version is 0 then we are upgrading from a file format that did not + // know about periodic syncs. In that case don't clear the list since we + // want the default, which is a daily periodioc sync. + // Otherwise clear out this default list since we will populate it later with + // the periodic sync descriptions that are read from the configuration file. + if (version > 0) { + authority.periodicSyncs.clear(); + } } if (authority != null) { authority.enabled = enabled == null || Boolean.parseBoolean(enabled); @@ -1443,6 +1469,7 @@ public class SyncStorageEngine extends Handler { } final Pair<Bundle, Long> periodicSync = Pair.create(extras, period); authority.periodicSyncs.add(periodicSync); + return periodicSync; } @@ -1491,6 +1518,7 @@ public class SyncStorageEngine extends Handler { out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); out.startTag(null, "accounts"); + out.attribute(null, "version", Integer.toString(ACCOUNTS_VERSION)); if (!mMasterSyncAutomatically) { out.attribute(null, "listen-for-tickles", "false"); } @@ -1505,7 +1533,7 @@ public class SyncStorageEngine extends Handler { out.attribute(null, "authority", authority.authority); if (!authority.enabled) { out.attribute(null, "enabled", "false"); - } + } if (authority.syncable < 0) { out.attribute(null, "syncable", "unknown"); } else if (authority.syncable == 0) { diff --git a/core/tests/coretests/src/android/content/SyncStorageEngineTest.java b/core/tests/coretests/src/android/content/SyncStorageEngineTest.java index 1505a7c..7028d1a 100644 --- a/core/tests/coretests/src/android/content/SyncStorageEngineTest.java +++ b/core/tests/coretests/src/android/content/SyncStorageEngineTest.java @@ -16,6 +16,8 @@ package android.content; +import com.android.internal.os.AtomicFile; + import android.test.AndroidTestCase; import android.test.RenamingDelegatingContext; import android.test.suitebuilder.annotation.SmallTest; @@ -26,6 +28,7 @@ import android.os.Bundle; import java.util.List; import java.io.File; +import java.io.FileOutputStream; public class SyncStorageEngineTest extends AndroidTestCase { @@ -193,6 +196,109 @@ public class SyncStorageEngineTest extends AndroidTestCase { assertEquals(1, engine.getIsSyncable(account1, authority2)); assertEquals(0, engine.getIsSyncable(account2, authority2)); } + + @SmallTest + public void testAuthorityParsing() throws Exception { + final Account account = new Account("account1", "type1"); + final String authority1 = "auth1"; + final String authority2 = "auth2"; + final String authority3 = "auth3"; + final Bundle extras = new Bundle(); + PeriodicSync sync1 = new PeriodicSync(account, authority1, extras, (long) (60 * 60 * 24)); + PeriodicSync sync2 = new PeriodicSync(account, authority2, extras, (long) (60 * 60 * 24)); + PeriodicSync sync3 = new PeriodicSync(account, authority3, extras, (long) (60 * 60 * 24)); + PeriodicSync sync1s = new PeriodicSync(account, authority1, extras, 1000); + PeriodicSync sync2s = new PeriodicSync(account, authority2, extras, 1000); + PeriodicSync sync3s = new PeriodicSync(account, authority3, extras, 1000); + + MockContentResolver mockResolver = new MockContentResolver(); + + final TestContext testContext = new TestContext(mockResolver, getContext()); + SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); + + byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<accounts>\n" + + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n" + + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n" + + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n" + + "</accounts>\n").getBytes(); + + File syncDir = new File(new File(testContext.getFilesDir(), "system"), "sync"); + syncDir.mkdirs(); + AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml")); + FileOutputStream fos = accountInfoFile.startWrite(); + fos.write(accountsFileData); + accountInfoFile.finishWrite(fos); + + engine.clearAndReadState(); + + List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, authority1); + assertEquals(1, syncs.size()); + assertEquals(sync1, syncs.get(0)); + + syncs = engine.getPeriodicSyncs(account, authority2); + assertEquals(1, syncs.size()); + assertEquals(sync2, syncs.get(0)); + + syncs = engine.getPeriodicSyncs(account, authority3); + assertEquals(1, syncs.size()); + assertEquals(sync3, syncs.get(0)); + + accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<accounts version=\"1\">\n" + + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n" + + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n" + + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n" + + "</accounts>\n").getBytes(); + + accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml")); + fos = accountInfoFile.startWrite(); + fos.write(accountsFileData); + accountInfoFile.finishWrite(fos); + + engine.clearAndReadState(); + + syncs = engine.getPeriodicSyncs(account, authority1); + assertEquals(0, syncs.size()); + + syncs = engine.getPeriodicSyncs(account, authority2); + assertEquals(0, syncs.size()); + + syncs = engine.getPeriodicSyncs(account, authority3); + assertEquals(0, syncs.size()); + + accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<accounts version=\"1\">\n" + + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n" + + "<periodicSync period=\"1000\" />\n" + + "</authority>" + + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\">\n" + + "<periodicSync period=\"1000\" />\n" + + "</authority>" + + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\">\n" + + "<periodicSync period=\"1000\" />\n" + + "</authority>" + + "</accounts>\n").getBytes(); + + accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml")); + fos = accountInfoFile.startWrite(); + fos.write(accountsFileData); + accountInfoFile.finishWrite(fos); + + engine.clearAndReadState(); + + syncs = engine.getPeriodicSyncs(account, authority1); + assertEquals(1, syncs.size()); + assertEquals(sync1s, syncs.get(0)); + + syncs = engine.getPeriodicSyncs(account, authority2); + assertEquals(1, syncs.size()); + assertEquals(sync2s, syncs.get(0)); + + syncs = engine.getPeriodicSyncs(account, authority3); + assertEquals(1, syncs.size()); + assertEquals(sync3s, syncs.get(0)); + } } class TestContext extends ContextWrapper { |