diff options
author | Dmitri Plotnikov <dplotnikov@google.com> | 2009-10-30 15:16:07 -0700 |
---|---|---|
committer | Dmitri Plotnikov <dplotnikov@google.com> | 2009-10-30 15:16:07 -0700 |
commit | 627152453c692915ac79191acd1d2d2a4dd6fb0d (patch) | |
tree | 3deb1bea5c7dd055c82b6eb76b5520ee517c3e19 | |
parent | e0f854c10f7a3aeebc9a7be9fb2bb101d70c01e4 (diff) | |
download | ContactsProvider-627152453c692915ac79191acd1d2d2a4dd6fb0d.tar.gz |
Making the first account "adopt" contacts created on the phone before any accounts
Bug: http://b/2222360
Change-Id: If55205305e0673ab3e22f8da5086a772f9990c22
3 files changed, 115 insertions, 36 deletions
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java index 337cc9b9..03d6293f 100644 --- a/src/com/android/providers/contacts/ContactsProvider2.java +++ b/src/com/android/providers/contacts/ContactsProvider2.java @@ -53,8 +53,10 @@ import android.content.ContentValues; import android.content.Context; import android.content.Entity; import android.content.EntityIterator; +import android.content.IContentService; import android.content.OperationApplicationException; import android.content.SharedPreferences; +import android.content.SyncAdapterType; import android.content.UriMatcher; import android.content.SharedPreferences.Editor; import android.content.res.AssetFileDescriptor; @@ -2959,7 +2961,7 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun mVisibleTouched = true; } if (updatedValues.containsKey(Groups.SHOULD_SYNC) - && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { + && updatedValues.getAsInteger(Groups.SHOULD_SYNC) != 0) { final long groupId = ContentUris.parseId(uri); Cursor c = mDb.query(Tables.GROUPS, new String[]{Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE}, Groups._ID + "=" + groupId, null, null, @@ -2972,7 +2974,7 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun accountType = c.getString(1); if(!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { Account account = new Account(accountName, accountType); - ContentResolver.requestSync(account, ContactsContract.AUTHORITY, + ContentResolver.requestSync(account, ContactsContract.AUTHORITY, new Bundle()); break; } @@ -3223,45 +3225,79 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun mDb = mDbHelper.getWritableDatabase(); if (mDb == null) return; - Set<Account> validAccounts = Sets.newHashSet(); - for (Account account : accounts) { - validAccounts.add(new Account(account.name, account.type)); - } - ArrayList<Account> accountsToDelete = new ArrayList<Account>(); - + HashSet<Account> existingAccounts = new HashSet<Account>(); + boolean hasUnassignedContacts[] = new boolean[]{false}; mDb.beginTransaction(); try { + findValidAccounts(existingAccounts, hasUnassignedContacts, + Tables.RAW_CONTACTS, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE); + findValidAccounts(existingAccounts, hasUnassignedContacts, + Tables.GROUPS, Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE); + findValidAccounts(existingAccounts, hasUnassignedContacts, + Tables.SETTINGS, Settings.ACCOUNT_NAME, Settings.ACCOUNT_TYPE); - for (String table : new String[]{Tables.RAW_CONTACTS, Tables.GROUPS, Tables.SETTINGS}) { - // Find all the accounts the contacts DB knows about, mark the ones that aren't - // in the valid set for deletion. - Cursor c = mDb.rawQuery("SELECT DISTINCT account_name, account_type from " - + table, null); - while (c.moveToNext()) { - if (c.getString(0) != null && c.getString(1) != null) { - Account currAccount = new Account(c.getString(0), c.getString(1)); - if (!validAccounts.contains(currAccount)) { - accountsToDelete.add(currAccount); - } - } - } - c.close(); + // Remove all valid accounts from the existing account set. What is left + // in the existingAccounts set will be extra accounts whose data must be deleted. + HashSet<Account> accountsToDelete = new HashSet<Account>(existingAccounts); + for (Account account : accounts) { + accountsToDelete.remove(account); } for (Account account : accountsToDelete) { Log.d(TAG, "removing data for removed account " + account); - String[] params = new String[]{account.name, account.type}; - mDb.execSQL("DELETE FROM " + Tables.GROUPS - + " WHERE account_name = ? AND account_type = ?", params); - mDb.execSQL("DELETE FROM " + Tables.PRESENCE - + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (SELECT " - + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS - + " WHERE account_name = ? AND account_type = ?)", params); - mDb.execSQL("DELETE FROM " + Tables.RAW_CONTACTS - + " WHERE account_name = ? AND account_type = ?", params); - mDb.execSQL("DELETE FROM " + Tables.SETTINGS - + " WHERE account_name = ? AND account_type = ?", params); + String[] params = new String[] {account.name, account.type}; + mDb.execSQL( + "DELETE FROM " + Tables.GROUPS + + " WHERE " + Groups.ACCOUNT_NAME + " = ?" + + " AND " + Groups.ACCOUNT_TYPE + " = ?", params); + mDb.execSQL( + "DELETE FROM " + Tables.PRESENCE + + " WHERE " + PresenceColumns.RAW_CONTACT_ID + " IN (" + + "SELECT " + RawContacts._ID + + " FROM " + Tables.RAW_CONTACTS + + " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + + " AND " + RawContacts.ACCOUNT_TYPE + " = ?)", params); + mDb.execSQL( + "DELETE FROM " + Tables.RAW_CONTACTS + + " WHERE " + RawContacts.ACCOUNT_NAME + " = ?" + + " AND " + RawContacts.ACCOUNT_TYPE + " = ?", params); + mDb.execSQL( + "DELETE FROM " + Tables.SETTINGS + + " WHERE " + Settings.ACCOUNT_NAME + " = ?" + + " AND " + Settings.ACCOUNT_TYPE + " = ?", params); + } + + if (hasUnassignedContacts[0]) { + + Account primaryAccount = null; + for (Account account : accounts) { + if (isWritableAccount(account)) { + primaryAccount = account; + break; + } + } + + if (primaryAccount != null) { + String[] params = new String[] {primaryAccount.name, primaryAccount.type}; + + mDb.execSQL( + "UPDATE " + Tables.RAW_CONTACTS + + " SET " + RawContacts.ACCOUNT_NAME + "=?," + + RawContacts.ACCOUNT_TYPE + "=?" + + " WHERE " + RawContacts.ACCOUNT_NAME + " IS NULL" + + " AND " + RawContacts.ACCOUNT_TYPE + " IS NULL", params); + + // We don't currently support groups for unsynced accounts, so this is for + // the future + mDb.execSQL( + "UPDATE " + Tables.GROUPS + + " SET " + Groups.ACCOUNT_NAME + "=?," + + Groups.ACCOUNT_TYPE + "=?" + + " WHERE " + Groups.ACCOUNT_NAME + " IS NULL" + + " AND " + Groups.ACCOUNT_TYPE + " IS NULL", params); + } } + mDbHelper.getSyncState().onAccountsChanged(mDb, accounts); mDb.setTransactionSuccessful(); } finally { @@ -3270,6 +3306,26 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun } /** + * Finds all distinct accounts present in the specified table. + */ + private void findValidAccounts(Set<Account> validAccounts, boolean[] hasUnassignedContacts, + String table, String accountNameColumn, String accountTypeColumn) { + Cursor c = mDb.rawQuery("SELECT DISTINCT " + accountNameColumn + "," + accountTypeColumn + + " FROM " + table, null); + try { + while (c.moveToNext()) { + if (c.isNull(0) && c.isNull(1)) { + hasUnassignedContacts[0] = true; + } else { + validAccounts.add(new Account(c.getString(0), c.getString(1))); + } + } + } finally { + c.close(); + } + } + + /** * Test all against {@link TextUtils#isEmpty(CharSequence)}. */ private static boolean areAllEmpty(ContentValues values, String[] keys) { @@ -4987,4 +5043,20 @@ public class ContactsProvider2 extends SQLiteContentProvider implements OnAccoun } return null; } + + protected boolean isWritableAccount(Account account) { + IContentService contentService = ContentResolver.getContentService(); + try { + for (SyncAdapterType sync : contentService.getSyncAdapterTypes()) { + if (ContactsContract.AUTHORITY.equals(sync.authority) && + account.type.equals(sync.accountType)) { + return sync.supportsUploading(); + } + } + } catch (RemoteException e) { + Log.e(TAG, "Could not acquire sync adapter types"); + } + + return false; + } } diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java index 11acf376..afeb377d 100644 --- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java +++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java @@ -1305,7 +1305,7 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { assertStoredValue(uri, RawContacts.DELETED, "1"); } - public void testContactDeletionAccountsUpdated() { + public void testAccountsUpdated() { long rawContactId1 = createRawContact(mAccount); insertEmail(rawContactId1, "account1@email.com"); long rawContactId2 = createRawContact(mAccountTwo); @@ -1318,15 +1318,17 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test { // accidentally. long rawContactId3 = createRawContactWithName("James", "Sullivan"); insertPhoneNumber(rawContactId3, "5234567890"); + Uri rawContact3 = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId3); ContactsProvider2 cp = (ContactsProvider2) getProvider(); Account accountRemaining = new Account("account1", "account type1"); cp.onAccountsUpdated(new Account[]{accountRemaining}); - Cursor c = mResolver.query(RawContacts.CONTENT_URI, null, null, null, null); - assertEquals(2, c.getCount()); + assertEquals(2, getCount(RawContacts.CONTENT_URI, null, null)); assertEquals(0, getCount(StatusUpdates.CONTENT_URI, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId2, null)); + assertStoredValue(rawContact3, RawContacts.ACCOUNT_NAME, "account1"); + assertStoredValue(rawContact3, RawContacts.ACCOUNT_TYPE, "account type1"); } public void testContactDeletion() { diff --git a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java index 7d814193..f5a35724 100644 --- a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java +++ b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java @@ -96,6 +96,11 @@ public class SynchronousContactsProvider2 extends ContactsProvider2 { return mAccount; } + @Override + protected boolean isWritableAccount(Account account) { + return true; + } + public void prepareForFullAggregation(int maxContact) { SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); db.execSQL("UPDATE raw_contacts SET aggregation_mode=0,aggregation_needed=1;"); |