summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/providers/contacts/ContactDirectoryManager.java41
-rw-r--r--tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java68
2 files changed, 105 insertions, 4 deletions
diff --git a/src/com/android/providers/contacts/ContactDirectoryManager.java b/src/com/android/providers/contacts/ContactDirectoryManager.java
index c014105..f2c8422 100644
--- a/src/com/android/providers/contacts/ContactDirectoryManager.java
+++ b/src/com/android/providers/contacts/ContactDirectoryManager.java
@@ -195,12 +195,44 @@ public class ContactDirectoryManager {
List<PackageInfo> packages = pm.getInstalledPackages(
PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA);
if (packages != null) {
+ // Prepare query strings for removing stale rows which don't correspond to existing
+ // directories.
+ StringBuilder deleteWhereBuilder = new StringBuilder();
+ ArrayList<String> deleteWhereArgs = new ArrayList<String>();
+ deleteWhereBuilder.append("NOT (" + Directory._ID + "=? OR " + Directory._ID + "=?");
+ deleteWhereArgs.add(String.valueOf(Directory.DEFAULT));
+ deleteWhereArgs.add(String.valueOf(Directory.LOCAL_INVISIBLE));
+ final String wherePart = "(" + Directory.PACKAGE_NAME + "=? AND "
+ + Directory.DIRECTORY_AUTHORITY + "=? AND "
+ + Directory.ACCOUNT_NAME + "=? AND "
+ + Directory.ACCOUNT_TYPE + "=?)";
+
for (PackageInfo packageInfo : packages) {
// Check all packages except the one containing ContactsProvider itself
if (!packageInfo.packageName.equals(mContext.getPackageName())) {
- count += updateDirectoriesForPackage(packageInfo, true);
+ List<DirectoryInfo> directories =
+ updateDirectoriesForPackage(packageInfo, true);
+ if (directories != null && !directories.isEmpty()) {
+ count += directories.size();
+
+ // We shouldn't delete rows for existing directories.
+ for (DirectoryInfo info : directories) {
+ deleteWhereBuilder.append(" OR ");
+ deleteWhereBuilder.append(wherePart);
+ deleteWhereArgs.add(info.packageName);
+ deleteWhereArgs.add(info.authority);
+ deleteWhereArgs.add(info.accountName);
+ deleteWhereArgs.add(info.accountType);
+ }
+ }
}
}
+
+ deleteWhereBuilder.append(")"); // Close "NOT ("
+ int deletedRows = db.delete(Tables.DIRECTORIES, deleteWhereBuilder.toString(),
+ deleteWhereArgs.toArray(new String[0]));
+ Log.i(TAG, "deleted " + deletedRows
+ + " stale rows which don't have any relevant directory");
}
return count;
}
@@ -258,7 +290,8 @@ public class ContactDirectoryManager {
* Scans the specified package for content directories and updates the {@link Directory}
* table accordingly.
*/
- private int updateDirectoriesForPackage(PackageInfo packageInfo, boolean initialScan) {
+ private List<DirectoryInfo> updateDirectoriesForPackage(
+ PackageInfo packageInfo, boolean initialScan) {
ArrayList<DirectoryInfo> directories = Lists.newArrayList();
ProviderInfo[] providers = packageInfo.providers;
@@ -275,7 +308,7 @@ public class ContactDirectoryManager {
}
if (directories.size() == 0 && initialScan) {
- return 0;
+ return null;
}
SQLiteDatabase db = getDbHelper().getWritableDatabase();
@@ -299,7 +332,7 @@ public class ContactDirectoryManager {
}
mContactsProvider.resetDirectoryCache();
- return directories.size();
+ return directories;
}
/**
diff --git a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
index 9ebc3d9..a0941a3 100644
--- a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
+++ b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
@@ -78,6 +78,8 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
String sortOrder) {
if (uri.toString().equals("content://" + mAuthority + "/directories")) {
+ // Should tolerate multiple queries.
+ mResponse.moveToPosition(-1);
return mResponse;
} else if (uri.toString().startsWith("content://" + mAuthority + "/contacts")) {
MatrixCursor cursor = new MatrixCursor(
@@ -309,6 +311,72 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
cursor.close();
}
+ /**
+ * Tests if the manager works correctly when the package name for a directory is changed
+ * (on system update).
+ */
+ public void testPackageRenamed() throws Exception {
+ mPackageManager.setInstalledPackages(
+ Lists.newArrayList(
+ createProviderPackage("test.package1", "authority1"),
+ createProviderPackage("test.package2", "authority2")));
+
+ MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
+ MockContactDirectoryProvider.class, "authority1");
+
+ MatrixCursor response1 = provider1.createResponseCursor();
+ addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
+ Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
+ Directory.PHOTO_SUPPORT_NONE);
+
+ MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider(
+ MockContactDirectoryProvider.class, "authority2");
+
+ MatrixCursor response2 = provider2.createResponseCursor();
+ addDirectoryRow(response2, "account-name2", "account-type2", "display-name2", 2,
+ Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
+ Directory.PHOTO_SUPPORT_FULL);
+
+ mDirectoryManager.scanAllPackages();
+
+ // At this point the manager has discovered two custom directories.
+ Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
+ assertEquals(4, cursor.getCount());
+ cursor.close();
+
+ // Pretend to rename the package name of a package on system update.
+ PackageInfo info = mPackageManager.getInstalledPackages(0).get(1);
+ info.packageName = "test.package3";
+ info.providers[0].packageName = "test.package3";
+ MatrixCursor response3 = provider2.createResponseCursor();
+ // Change resource id.
+ addDirectoryRow(response3, "account-name2", "account-type2", "display-name2", 3,
+ Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
+ Directory.PHOTO_SUPPORT_FULL);
+
+ // When this happens on reboot, scanAllPackages() is called instead of onPackageChanged()
+ // (as part of ContactsProvider2 initialization).
+ // Accounts won't be affected so false should be passed here.
+ mDirectoryManager.scanAllPackages(false);
+
+ cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
+ // We should have columns for default, local_invisible, test.package1, and test.package3.
+ // The row for test.package2 should not remain.
+ assertEquals(4, cursor.getCount());
+
+ cursor.moveToPosition(2);
+ assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1",
+ "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
+ Directory.PHOTO_SUPPORT_NONE);
+
+ cursor.moveToNext();
+ assertDirectoryRow(cursor, "test.package3", "authority2", "account-name2", "account-type2",
+ "display-name2", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY,
+ Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
+
+ cursor.close();
+ }
+
public void testAccountRemoval() throws Exception {
mPackageManager.setInstalledPackages(
Lists.newArrayList(