Loading core/java/android/content/SyncManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -215,7 +215,9 @@ public class SyncManager implements OnAccountsUpdateListener { // the accounts are not set yet sendCheckAlarmsMessage(); if (mBootCompleted) { mSyncStorageEngine.doDatabaseCleanup(accounts); } if (accounts.length > 0) { // If this is the first time this was called after a bootup then Loading Loading @@ -1317,6 +1319,7 @@ public class SyncManager implements OnAccountsUpdateListener { private volatile CountDownLatch mReadyToRunLatch = new CountDownLatch(1); public void onBootCompleted() { mBootCompleted = true; mSyncStorageEngine.doDatabaseCleanup(AccountManager.get(mContext).getAccounts()); if (mReadyToRunLatch != null) { mReadyToRunLatch.countDown(); } Loading core/java/android/content/SyncStorageEngine.java +70 −11 Original line number Diff line number Diff line Loading @@ -122,7 +122,15 @@ 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; private static final int ACCOUNTS_VERSION = 2; private static HashMap<String, String> sAuthorityRenames; static { sAuthorityRenames = new HashMap<String, String>(); sAuthorityRenames.put("contacts", "com.android.contacts"); sAuthorityRenames.put("calendar", "com.android.calendar"); } public static class PendingOperation { final Account account; Loading Loading @@ -1281,7 +1289,9 @@ public class SyncStorageEngine extends Handler { private void removeAuthorityLocked(Account account, String authorityName) { AccountInfo accountInfo = mAccounts.get(account); if (accountInfo != null) { if (accountInfo.authorities.remove(authorityName) != null) { final AuthorityInfo authorityInfo = accountInfo.authorities.remove(authorityName); if (authorityInfo != null) { mAuthorities.remove(authorityInfo.ident); writeAccountInfoLocked(); } } Loading Loading @@ -1407,11 +1417,61 @@ public class SyncStorageEngine extends Handler { } } if (maybeMigrateSettingsForRenamedAuthorities()) { writeNeeded = true; } if (writeNeeded) { writeAccountInfoLocked(); } } /** * some authority names have changed. copy over their settings and delete the old ones * @return true if a change was made */ private boolean maybeMigrateSettingsForRenamedAuthorities() { boolean writeNeeded = false; ArrayList<AuthorityInfo> authoritiesToRemove = new ArrayList<AuthorityInfo>(); final int N = mAuthorities.size(); for (int i=0; i<N; i++) { AuthorityInfo authority = mAuthorities.valueAt(i); // skip this authority if it isn't one of the renamed ones final String newAuthorityName = sAuthorityRenames.get(authority.authority); if (newAuthorityName == null) { continue; } // remember this authority so we can remove it later. we can't remove it // now without messing up this loop iteration authoritiesToRemove.add(authority); // this authority isn't enabled, no need to copy it to the new authority name since // the default is "disabled" if (!authority.enabled) { continue; } // if we already have a record of this new authority then don't copy over the settings if (getAuthorityLocked(authority.account, newAuthorityName, "cleanup") != null) { continue; } AuthorityInfo newAuthority = getOrCreateAuthorityLocked(authority.account, newAuthorityName, -1 /* ident */, false /* doWrite */); newAuthority.enabled = true; writeNeeded = true; } for (AuthorityInfo authorityInfo : authoritiesToRemove) { removeAuthorityLocked(authorityInfo.account, authorityInfo.authority); writeNeeded = true; } return writeNeeded; } private AuthorityInfo parseAuthority(XmlPullParser parser, int version) { AuthorityInfo authority = null; int id = -1; Loading @@ -1424,14 +1484,15 @@ public class SyncStorageEngine extends Handler { Log.e(TAG, "the id of the authority is null", e); } if (id >= 0) { String authorityName = parser.getAttributeValue(null, "authority"); String enabled = parser.getAttributeValue(null, "enabled"); String syncable = parser.getAttributeValue(null, "syncable"); String accountName = parser.getAttributeValue(null, "account"); String accountType = parser.getAttributeValue(null, "type"); if (accountType == null) { accountType = "com.google"; syncable = "unknown"; } String authorityName = parser.getAttributeValue(null, "authority"); String enabled = parser.getAttributeValue(null, "enabled"); String syncable = parser.getAttributeValue(null, "syncable"); authority = mAuthorities.get(id); if (DEBUG_FILE) Log.v(TAG, "Adding authority: account=" + accountName + " auth=" + authorityName Loading @@ -1456,7 +1517,7 @@ public class SyncStorageEngine extends Handler { authority.syncable = -1; } else { authority.syncable = (syncable == null || Boolean.parseBoolean(enabled)) ? 1 : 0; (syncable == null || Boolean.parseBoolean(syncable)) ? 1 : 0; } } else { Log.w(TAG, "Failure adding authority: account=" Loading Loading @@ -1546,13 +1607,11 @@ public class SyncStorageEngine extends Handler { out.attribute(null, "account", authority.account.name); out.attribute(null, "type", authority.account.type); out.attribute(null, "authority", authority.authority); if (!authority.enabled) { out.attribute(null, "enabled", "false"); } out.attribute(null, "enabled", Boolean.toString(authority.enabled)); if (authority.syncable < 0) { out.attribute(null, "syncable", "unknown"); } else if (authority.syncable == 0) { out.attribute(null, "syncable", "false"); } else { out.attribute(null, "syncable", Boolean.toString(authority.syncable != 0)); } for (Pair<Bundle, Long> periodicSync : authority.periodicSyncs) { out.startTag(null, "periodicSync"); Loading core/tests/coretests/src/android/content/SyncStorageEngineTest.java +86 −4 Original line number Diff line number Diff line Loading @@ -214,7 +214,6 @@ public class SyncStorageEngineTest extends AndroidTestCase { 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" Loading @@ -230,7 +229,7 @@ public class SyncStorageEngineTest extends AndroidTestCase { fos.write(accountsFileData); accountInfoFile.finishWrite(fos); engine.clearAndReadState(); SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, authority1); assertEquals(1, syncs.size()); Loading @@ -245,7 +244,7 @@ public class SyncStorageEngineTest extends AndroidTestCase { assertEquals(sync3, syncs.get(0)); accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts version=\"1\">\n" + "<accounts version=\"2\">\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" Loading @@ -268,7 +267,7 @@ public class SyncStorageEngineTest extends AndroidTestCase { assertEquals(0, syncs.size()); accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts version=\"1\">\n" + "<accounts version=\"2\">\n" + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n" + "<periodicSync period=\"1000\" />\n" + "</authority>" Loading Loading @@ -299,6 +298,89 @@ public class SyncStorageEngineTest extends AndroidTestCase { assertEquals(1, syncs.size()); assertEquals(sync3s, syncs.get(0)); } @SmallTest public void testAuthorityRenaming() throws Exception { final Account account1 = new Account("acc1", "type1"); final Account account2 = new Account("acc2", "type2"); final String authorityContacts = "contacts"; final String authorityCalendar = "calendar"; final String authorityOther = "other"; final String authorityContactsNew = "com.android.contacts"; final String authorityCalendarNew = "com.android.calendar"; MockContentResolver mockResolver = new MockContentResolver(); final TestContext testContext = new TestContext(mockResolver, getContext()); byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts>\n" + "<authority id=\"0\" account=\"acc1\" type=\"type1\" authority=\"contacts\" />\n" + "<authority id=\"1\" account=\"acc1\" type=\"type1\" authority=\"calendar\" />\n" + "<authority id=\"2\" account=\"acc1\" type=\"type1\" authority=\"other\" />\n" + "<authority id=\"3\" account=\"acc2\" type=\"type2\" authority=\"contacts\" />\n" + "<authority id=\"4\" account=\"acc2\" type=\"type2\" authority=\"calendar\" />\n" + "<authority id=\"5\" account=\"acc2\" type=\"type2\" authority=\"other\" />\n" + "<authority id=\"6\" account=\"acc2\" type=\"type2\" enabled=\"false\"" + " authority=\"com.android.calendar\" />\n" + "<authority id=\"7\" account=\"acc2\" type=\"type2\" enabled=\"false\"" + " authority=\"com.android.contacts\" />\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); SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); assertEquals(false, engine.getSyncAutomatically(account1, authorityContacts)); assertEquals(false, engine.getSyncAutomatically(account1, authorityCalendar)); assertEquals(true, engine.getSyncAutomatically(account1, authorityOther)); assertEquals(true, engine.getSyncAutomatically(account1, authorityContactsNew)); assertEquals(true, engine.getSyncAutomatically(account1, authorityCalendarNew)); assertEquals(false, engine.getSyncAutomatically(account2, authorityContacts)); assertEquals(false, engine.getSyncAutomatically(account2, authorityCalendar)); assertEquals(true, engine.getSyncAutomatically(account2, authorityOther)); assertEquals(false, engine.getSyncAutomatically(account2, authorityContactsNew)); assertEquals(false, engine.getSyncAutomatically(account2, authorityCalendarNew)); } @SmallTest public void testSyncableMigration() throws Exception { final Account account = new Account("acc", "type"); MockContentResolver mockResolver = new MockContentResolver(); final TestContext testContext = new TestContext(mockResolver, getContext()); byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts>\n" + "<authority id=\"0\" account=\"acc\" authority=\"other1\" />\n" + "<authority id=\"1\" account=\"acc\" type=\"type\" authority=\"other2\" />\n" + "<authority id=\"2\" account=\"acc\" type=\"type\" syncable=\"false\"" + " authority=\"other3\" />\n" + "<authority id=\"3\" account=\"acc\" type=\"type\" syncable=\"true\"" + " authority=\"other4\" />\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); SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); assertEquals(-1, engine.getIsSyncable(account, "other1")); assertEquals(1, engine.getIsSyncable(account, "other2")); assertEquals(0, engine.getIsSyncable(account, "other3")); assertEquals(1, engine.getIsSyncable(account, "other4")); } } class TestContext extends ContextWrapper { Loading Loading
core/java/android/content/SyncManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -215,7 +215,9 @@ public class SyncManager implements OnAccountsUpdateListener { // the accounts are not set yet sendCheckAlarmsMessage(); if (mBootCompleted) { mSyncStorageEngine.doDatabaseCleanup(accounts); } if (accounts.length > 0) { // If this is the first time this was called after a bootup then Loading Loading @@ -1317,6 +1319,7 @@ public class SyncManager implements OnAccountsUpdateListener { private volatile CountDownLatch mReadyToRunLatch = new CountDownLatch(1); public void onBootCompleted() { mBootCompleted = true; mSyncStorageEngine.doDatabaseCleanup(AccountManager.get(mContext).getAccounts()); if (mReadyToRunLatch != null) { mReadyToRunLatch.countDown(); } Loading
core/java/android/content/SyncStorageEngine.java +70 −11 Original line number Diff line number Diff line Loading @@ -122,7 +122,15 @@ 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; private static final int ACCOUNTS_VERSION = 2; private static HashMap<String, String> sAuthorityRenames; static { sAuthorityRenames = new HashMap<String, String>(); sAuthorityRenames.put("contacts", "com.android.contacts"); sAuthorityRenames.put("calendar", "com.android.calendar"); } public static class PendingOperation { final Account account; Loading Loading @@ -1281,7 +1289,9 @@ public class SyncStorageEngine extends Handler { private void removeAuthorityLocked(Account account, String authorityName) { AccountInfo accountInfo = mAccounts.get(account); if (accountInfo != null) { if (accountInfo.authorities.remove(authorityName) != null) { final AuthorityInfo authorityInfo = accountInfo.authorities.remove(authorityName); if (authorityInfo != null) { mAuthorities.remove(authorityInfo.ident); writeAccountInfoLocked(); } } Loading Loading @@ -1407,11 +1417,61 @@ public class SyncStorageEngine extends Handler { } } if (maybeMigrateSettingsForRenamedAuthorities()) { writeNeeded = true; } if (writeNeeded) { writeAccountInfoLocked(); } } /** * some authority names have changed. copy over their settings and delete the old ones * @return true if a change was made */ private boolean maybeMigrateSettingsForRenamedAuthorities() { boolean writeNeeded = false; ArrayList<AuthorityInfo> authoritiesToRemove = new ArrayList<AuthorityInfo>(); final int N = mAuthorities.size(); for (int i=0; i<N; i++) { AuthorityInfo authority = mAuthorities.valueAt(i); // skip this authority if it isn't one of the renamed ones final String newAuthorityName = sAuthorityRenames.get(authority.authority); if (newAuthorityName == null) { continue; } // remember this authority so we can remove it later. we can't remove it // now without messing up this loop iteration authoritiesToRemove.add(authority); // this authority isn't enabled, no need to copy it to the new authority name since // the default is "disabled" if (!authority.enabled) { continue; } // if we already have a record of this new authority then don't copy over the settings if (getAuthorityLocked(authority.account, newAuthorityName, "cleanup") != null) { continue; } AuthorityInfo newAuthority = getOrCreateAuthorityLocked(authority.account, newAuthorityName, -1 /* ident */, false /* doWrite */); newAuthority.enabled = true; writeNeeded = true; } for (AuthorityInfo authorityInfo : authoritiesToRemove) { removeAuthorityLocked(authorityInfo.account, authorityInfo.authority); writeNeeded = true; } return writeNeeded; } private AuthorityInfo parseAuthority(XmlPullParser parser, int version) { AuthorityInfo authority = null; int id = -1; Loading @@ -1424,14 +1484,15 @@ public class SyncStorageEngine extends Handler { Log.e(TAG, "the id of the authority is null", e); } if (id >= 0) { String authorityName = parser.getAttributeValue(null, "authority"); String enabled = parser.getAttributeValue(null, "enabled"); String syncable = parser.getAttributeValue(null, "syncable"); String accountName = parser.getAttributeValue(null, "account"); String accountType = parser.getAttributeValue(null, "type"); if (accountType == null) { accountType = "com.google"; syncable = "unknown"; } String authorityName = parser.getAttributeValue(null, "authority"); String enabled = parser.getAttributeValue(null, "enabled"); String syncable = parser.getAttributeValue(null, "syncable"); authority = mAuthorities.get(id); if (DEBUG_FILE) Log.v(TAG, "Adding authority: account=" + accountName + " auth=" + authorityName Loading @@ -1456,7 +1517,7 @@ public class SyncStorageEngine extends Handler { authority.syncable = -1; } else { authority.syncable = (syncable == null || Boolean.parseBoolean(enabled)) ? 1 : 0; (syncable == null || Boolean.parseBoolean(syncable)) ? 1 : 0; } } else { Log.w(TAG, "Failure adding authority: account=" Loading Loading @@ -1546,13 +1607,11 @@ public class SyncStorageEngine extends Handler { out.attribute(null, "account", authority.account.name); out.attribute(null, "type", authority.account.type); out.attribute(null, "authority", authority.authority); if (!authority.enabled) { out.attribute(null, "enabled", "false"); } out.attribute(null, "enabled", Boolean.toString(authority.enabled)); if (authority.syncable < 0) { out.attribute(null, "syncable", "unknown"); } else if (authority.syncable == 0) { out.attribute(null, "syncable", "false"); } else { out.attribute(null, "syncable", Boolean.toString(authority.syncable != 0)); } for (Pair<Bundle, Long> periodicSync : authority.periodicSyncs) { out.startTag(null, "periodicSync"); Loading
core/tests/coretests/src/android/content/SyncStorageEngineTest.java +86 −4 Original line number Diff line number Diff line Loading @@ -214,7 +214,6 @@ public class SyncStorageEngineTest extends AndroidTestCase { 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" Loading @@ -230,7 +229,7 @@ public class SyncStorageEngineTest extends AndroidTestCase { fos.write(accountsFileData); accountInfoFile.finishWrite(fos); engine.clearAndReadState(); SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, authority1); assertEquals(1, syncs.size()); Loading @@ -245,7 +244,7 @@ public class SyncStorageEngineTest extends AndroidTestCase { assertEquals(sync3, syncs.get(0)); accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts version=\"1\">\n" + "<accounts version=\"2\">\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" Loading @@ -268,7 +267,7 @@ public class SyncStorageEngineTest extends AndroidTestCase { assertEquals(0, syncs.size()); accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts version=\"1\">\n" + "<accounts version=\"2\">\n" + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n" + "<periodicSync period=\"1000\" />\n" + "</authority>" Loading Loading @@ -299,6 +298,89 @@ public class SyncStorageEngineTest extends AndroidTestCase { assertEquals(1, syncs.size()); assertEquals(sync3s, syncs.get(0)); } @SmallTest public void testAuthorityRenaming() throws Exception { final Account account1 = new Account("acc1", "type1"); final Account account2 = new Account("acc2", "type2"); final String authorityContacts = "contacts"; final String authorityCalendar = "calendar"; final String authorityOther = "other"; final String authorityContactsNew = "com.android.contacts"; final String authorityCalendarNew = "com.android.calendar"; MockContentResolver mockResolver = new MockContentResolver(); final TestContext testContext = new TestContext(mockResolver, getContext()); byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts>\n" + "<authority id=\"0\" account=\"acc1\" type=\"type1\" authority=\"contacts\" />\n" + "<authority id=\"1\" account=\"acc1\" type=\"type1\" authority=\"calendar\" />\n" + "<authority id=\"2\" account=\"acc1\" type=\"type1\" authority=\"other\" />\n" + "<authority id=\"3\" account=\"acc2\" type=\"type2\" authority=\"contacts\" />\n" + "<authority id=\"4\" account=\"acc2\" type=\"type2\" authority=\"calendar\" />\n" + "<authority id=\"5\" account=\"acc2\" type=\"type2\" authority=\"other\" />\n" + "<authority id=\"6\" account=\"acc2\" type=\"type2\" enabled=\"false\"" + " authority=\"com.android.calendar\" />\n" + "<authority id=\"7\" account=\"acc2\" type=\"type2\" enabled=\"false\"" + " authority=\"com.android.contacts\" />\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); SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); assertEquals(false, engine.getSyncAutomatically(account1, authorityContacts)); assertEquals(false, engine.getSyncAutomatically(account1, authorityCalendar)); assertEquals(true, engine.getSyncAutomatically(account1, authorityOther)); assertEquals(true, engine.getSyncAutomatically(account1, authorityContactsNew)); assertEquals(true, engine.getSyncAutomatically(account1, authorityCalendarNew)); assertEquals(false, engine.getSyncAutomatically(account2, authorityContacts)); assertEquals(false, engine.getSyncAutomatically(account2, authorityCalendar)); assertEquals(true, engine.getSyncAutomatically(account2, authorityOther)); assertEquals(false, engine.getSyncAutomatically(account2, authorityContactsNew)); assertEquals(false, engine.getSyncAutomatically(account2, authorityCalendarNew)); } @SmallTest public void testSyncableMigration() throws Exception { final Account account = new Account("acc", "type"); MockContentResolver mockResolver = new MockContentResolver(); final TestContext testContext = new TestContext(mockResolver, getContext()); byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<accounts>\n" + "<authority id=\"0\" account=\"acc\" authority=\"other1\" />\n" + "<authority id=\"1\" account=\"acc\" type=\"type\" authority=\"other2\" />\n" + "<authority id=\"2\" account=\"acc\" type=\"type\" syncable=\"false\"" + " authority=\"other3\" />\n" + "<authority id=\"3\" account=\"acc\" type=\"type\" syncable=\"true\"" + " authority=\"other4\" />\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); SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); assertEquals(-1, engine.getIsSyncable(account, "other1")); assertEquals(1, engine.getIsSyncable(account, "other2")); assertEquals(0, engine.getIsSyncable(account, "other3")); assertEquals(1, engine.getIsSyncable(account, "other4")); } } class TestContext extends ContextWrapper { Loading