Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f343ebe authored by Fred Quintana's avatar Fred Quintana Committed by Android (Google) Code Review
Browse files

Merge "fix bug where sync settings set lost upon upgrade from donut and eclair to froyo"

parents cbac8ac6 fb084400
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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
@@ -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();
            }
+70 −11
Original line number Diff line number Diff line
@@ -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;
@@ -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();
            }
        }
@@ -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;
@@ -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
@@ -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="
@@ -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");
+86 −4
Original line number Diff line number Diff line
@@ -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"
@@ -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());
@@ -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"
@@ -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>"
@@ -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 {