aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitri Plotnikov <dplotnikov@google.com>2009-10-30 15:16:07 -0700
committerDmitri Plotnikov <dplotnikov@google.com>2009-10-30 15:16:07 -0700
commit627152453c692915ac79191acd1d2d2a4dd6fb0d (patch)
tree3deb1bea5c7dd055c82b6eb76b5520ee517c3e19
parente0f854c10f7a3aeebc9a7be9fb2bb101d70c01e4 (diff)
downloadContactsProvider-627152453c692915ac79191acd1d2d2a4dd6fb0d.tar.gz
Making the first account "adopt" contacts created on the phone before any accounts
Bug: http://b/2222360 Change-Id: If55205305e0673ab3e22f8da5086a772f9990c22
-rw-r--r--src/com/android/providers/contacts/ContactsProvider2.java138
-rw-r--r--tests/src/com/android/providers/contacts/ContactsProvider2Test.java8
-rw-r--r--tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java5
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;");