Home | History | Annotate | Download | only in contacts
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.providers.contacts;
     18 
     19 import android.accounts.Account;
     20 import android.content.ContentValues;
     21 import android.content.Context;
     22 import android.content.pm.PackageInfo;
     23 import android.content.pm.PackageManager;
     24 import android.content.pm.PackageManager.NameNotFoundException;
     25 import android.content.pm.ProviderInfo;
     26 import android.database.Cursor;
     27 import android.database.MatrixCursor;
     28 import android.net.Uri;
     29 import android.os.Bundle;
     30 import android.provider.ContactsContract;
     31 import android.provider.ContactsContract.AggregationExceptions;
     32 import android.provider.ContactsContract.Contacts;
     33 import android.provider.ContactsContract.Directory;
     34 import android.provider.ContactsContract.RawContacts;
     35 import android.test.mock.MockContentProvider;
     36 import android.test.suitebuilder.annotation.MediumTest;
     37 import android.util.Log;
     38 
     39 import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
     40 import com.google.android.collect.Lists;
     41 
     42 /**
     43  * Unit tests for {@link ContactDirectoryManager}. Run the test like this:
     44  *
     45     adb shell am instrument -e class com.android.providers.contacts.ContactDirectoryManagerTest \
     46         -w com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
     47  *
     48  */
     49 @MediumTest
     50 public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
     51     private static final String TAG = "ContactDirectoryManagerTest";
     52 
     53     private ContactsMockPackageManager mPackageManager;
     54 
     55     private ContactsProvider2 mProvider;
     56 
     57     private ContactDirectoryManager mDirectoryManager;
     58 
     59     public static class MockContactDirectoryProvider extends MockContentProvider {
     60 
     61         private String mAuthority;
     62 
     63         private MatrixCursor mResponse;
     64 
     65         @Override
     66         public void attachInfoForTesting(Context context, ProviderInfo info) {
     67             mAuthority = info.authority;
     68         }
     69 
     70         public MatrixCursor createResponseCursor() {
     71             mResponse = new MatrixCursor(
     72                     new String[] { Directory.ACCOUNT_NAME, Directory.ACCOUNT_TYPE,
     73                             Directory.DISPLAY_NAME, Directory.TYPE_RESOURCE_ID,
     74                             Directory.EXPORT_SUPPORT, Directory.SHORTCUT_SUPPORT,
     75                             Directory.PHOTO_SUPPORT });
     76 
     77             return mResponse;
     78         }
     79 
     80         @Override
     81         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
     82                 String sortOrder) {
     83 
     84             if (uri.toString().equals("content://" + mAuthority + "/directories")) {
     85                 // Should tolerate multiple queries.
     86                 mResponse.moveToPosition(-1);
     87                 return mResponse;
     88             } else if (uri.toString().startsWith("content://" + mAuthority + "/contacts")) {
     89                 MatrixCursor cursor = new MatrixCursor(
     90                         new String[] { "projection", "selection", "selectionArgs", "sortOrder",
     91                                 "accountName", "accountType"});
     92                 cursor.addRow(new Object[] {
     93                     Lists.newArrayList(projection).toString(),
     94                     selection,
     95                     Lists.newArrayList(selectionArgs).toString(),
     96                     sortOrder,
     97                     uri.getQueryParameter(RawContacts.ACCOUNT_NAME),
     98                     uri.getQueryParameter(RawContacts.ACCOUNT_TYPE),
     99                 });
    100                 return cursor;
    101             } else if (uri.toString().startsWith(
    102                     "content://" + mAuthority + "/aggregation_exceptions")) {
    103                 return new MatrixCursor(projection);
    104             }
    105 
    106             fail("Unexpected uri: " + uri);
    107             return null;
    108         }
    109     }
    110 
    111     @Override
    112     public void setUp() throws Exception {
    113         super.setUp();
    114 
    115         mProvider = (ContactsProvider2) getProvider();
    116         mDirectoryManager = mProvider.getContactDirectoryManagerForTest();
    117 
    118         mPackageManager = (ContactsMockPackageManager) getProvider()
    119                 .getContext().getPackageManager();
    120     }
    121 
    122     public void testIsDirectoryProvider() {
    123         ProviderInfo provider = new ProviderInfo();
    124 
    125         // Null -- just return false.
    126         assertFalse(ContactDirectoryManager.isDirectoryProvider(null));
    127 
    128         // No metadata
    129         assertFalse(ContactDirectoryManager.isDirectoryProvider(provider));
    130 
    131         // No CONTACT_DIRECTORY_META_DATA
    132         provider.metaData = new Bundle();
    133         assertFalse(ContactDirectoryManager.isDirectoryProvider(provider));
    134 
    135         // CONTACT_DIRECTORY_META_DATA is a string
    136         provider.metaData.putString("android.content.ContactDirectory", "");
    137         assertFalse(ContactDirectoryManager.isDirectoryProvider(provider));
    138 
    139         // CONTACT_DIRECTORY_META_DATA is false
    140         provider.metaData.putBoolean("android.content.ContactDirectory", false);
    141         assertFalse(ContactDirectoryManager.isDirectoryProvider(provider));
    142 
    143         // CONTACT_DIRECTORY_META_DATA is true
    144         provider.metaData.putBoolean("android.content.ContactDirectory", true);
    145         assertTrue(ContactDirectoryManager.isDirectoryProvider(provider));
    146     }
    147 
    148     public void testScanAllProviders() throws Exception {
    149         mPackageManager.setInstalledPackages(
    150                 Lists.newArrayList(
    151                         createProviderPackage("test.package1", "authority1"),
    152                         createProviderPackage("test.package2", "authority2"),
    153                         createPackage("test.packageX", "authorityX", false)));
    154 
    155         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    156                 MockContactDirectoryProvider.class, "authority1");
    157 
    158         MatrixCursor response1 = provider1.createResponseCursor();
    159         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    160                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    161                 Directory.PHOTO_SUPPORT_FULL_SIZE_ONLY);
    162         addDirectoryRow(response1, "account-name2", "account-type2", "display-name2", 2,
    163                 Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY,
    164                 Directory.PHOTO_SUPPORT_THUMBNAIL_ONLY);
    165 
    166         MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider(
    167                 MockContactDirectoryProvider.class, "authority2");
    168 
    169         MatrixCursor response2 = provider2.createResponseCursor();
    170         addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3,
    171                 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
    172                 Directory.PHOTO_SUPPORT_FULL);
    173 
    174         mDirectoryManager.scanAllPackages();
    175 
    176         Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    177         assertEquals(5, cursor.getCount());
    178 
    179         cursor.moveToPosition(2);
    180         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1",
    181                 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    182                 Directory.PHOTO_SUPPORT_FULL_SIZE_ONLY);
    183 
    184         cursor.moveToNext();
    185         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name2", "account-type2",
    186                 "display-name2", 2, Directory.EXPORT_SUPPORT_ANY_ACCOUNT,
    187                 Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY, Directory.PHOTO_SUPPORT_THUMBNAIL_ONLY);
    188 
    189         cursor.moveToNext();
    190         assertDirectoryRow(cursor, "test.package2", "authority2", "account-name3", "account-type3",
    191                 "display-name3", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY,
    192                 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
    193 
    194         cursor.close();
    195     }
    196 
    197     public void testPackageInstalled() throws Exception {
    198         mPackageManager.setInstalledPackages(
    199                 Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
    200                         createPackage("test.packageX", "authorityX", false)));
    201 
    202         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    203                 MockContactDirectoryProvider.class, "authority1");
    204 
    205         MatrixCursor response1 = provider1.createResponseCursor();
    206         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    207                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    208                 Directory.PHOTO_SUPPORT_FULL);
    209 
    210         mDirectoryManager.scanAllPackages();
    211 
    212         // At this point the manager has discovered a single directory (plus two
    213         // standard ones).
    214         Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    215         assertEquals(3, cursor.getCount());
    216         cursor.close();
    217 
    218         // Pretend to install another package
    219         MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider(
    220                 MockContactDirectoryProvider.class, "authority2");
    221 
    222         MatrixCursor response2 = provider2.createResponseCursor();
    223         addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3,
    224                 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
    225                 Directory.PHOTO_SUPPORT_FULL);
    226 
    227         mPackageManager.getInstalledPackages(0).add(
    228                 createProviderPackage("test.package2", "authority2"));
    229 
    230         mProvider.onPackageChanged("test.package2");
    231 
    232         cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    233         assertEquals(4, cursor.getCount());
    234 
    235         cursor.moveToPosition(2);
    236         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1",
    237                 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    238                 Directory.PHOTO_SUPPORT_FULL);
    239 
    240         cursor.moveToNext();
    241         assertDirectoryRow(cursor, "test.package2", "authority2", "account-name3", "account-type3",
    242                 "display-name3", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY,
    243                 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
    244 
    245         cursor.close();
    246     }
    247 
    248     public void testPackageUninstalled() throws Exception {
    249         mPackageManager.setInstalledPackages(
    250                 Lists.newArrayList(
    251                         createProviderPackage("test.package1", "authority1"),
    252                         createProviderPackage("test.package2", "authority2"),
    253                         createPackage("test.packageX", "authorityX", false)));
    254 
    255         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    256                 MockContactDirectoryProvider.class, "authority1");
    257 
    258         MatrixCursor response1 = provider1.createResponseCursor();
    259         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    260                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    261                 Directory.PHOTO_SUPPORT_NONE);
    262 
    263         MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider(
    264                 MockContactDirectoryProvider.class, "authority2");
    265 
    266         MatrixCursor response2 = provider2.createResponseCursor();
    267         addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3,
    268                 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
    269                 Directory.PHOTO_SUPPORT_FULL);
    270 
    271         mDirectoryManager.scanAllPackages();
    272 
    273         // At this point the manager has discovered two custom directories.
    274         Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    275         assertEquals(4, cursor.getCount());
    276         cursor.close();
    277 
    278         // Pretend to uninstall one of the packages
    279         mPackageManager.getInstalledPackages(0).remove(1);
    280 
    281         mProvider.onPackageChanged("test.package2");
    282 
    283         cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    284         assertEquals(3, cursor.getCount());
    285 
    286         cursor.moveToPosition(2);
    287         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1",
    288                 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    289                 Directory.PHOTO_SUPPORT_NONE);
    290 
    291         cursor.close();
    292     }
    293 
    294     public void testPackageReplaced() throws Exception {
    295         mPackageManager.setInstalledPackages(
    296                 Lists.newArrayList(
    297                         createProviderPackage("test.package1", "authority1"),
    298                         createProviderPackage("test.package2", "authority2"),
    299                         createPackage("test.packageX", "authorityX", false)));
    300 
    301         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    302                 MockContactDirectoryProvider.class, "authority1");
    303 
    304         MatrixCursor response1 = provider1.createResponseCursor();
    305         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    306                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    307                 Directory.PHOTO_SUPPORT_NONE);
    308 
    309         MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider(
    310                 MockContactDirectoryProvider.class, "authority2");
    311 
    312         MatrixCursor response2 = provider2.createResponseCursor();
    313         addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3,
    314                 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
    315                 Directory.PHOTO_SUPPORT_FULL);
    316 
    317         mDirectoryManager.scanAllPackages();
    318 
    319         // At this point the manager has discovered two custom directories.
    320         Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    321         assertEquals(4, cursor.getCount());
    322         cursor.close();
    323 
    324         // Pretend to replace the package with a different provider inside
    325         MatrixCursor response3 = provider2.createResponseCursor();
    326         addDirectoryRow(response3, "account-name4", "account-type4", "display-name4", 4,
    327                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    328                 Directory.PHOTO_SUPPORT_NONE);
    329 
    330         mProvider.onPackageChanged("test.package2");
    331 
    332         cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    333         assertEquals(4, cursor.getCount());
    334 
    335         cursor.moveToPosition(2);
    336         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1",
    337                 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    338                 Directory.PHOTO_SUPPORT_NONE);
    339 
    340         cursor.moveToNext();
    341         assertDirectoryRow(cursor, "test.package2", "authority2", "account-name4", "account-type4",
    342                 "display-name4", 4, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    343                 Directory.PHOTO_SUPPORT_NONE);
    344 
    345         cursor.close();
    346     }
    347 
    348     /**
    349      * Tests if the manager works correctly when the package name for a directory is changed
    350      * (on system update).
    351      */
    352     public void testPackageRenamed() throws Exception {
    353         mPackageManager.setInstalledPackages(
    354                 Lists.newArrayList(
    355                         createProviderPackage("test.package1", "authority1"),
    356                         createProviderPackage("test.package2", "authority2"),
    357                         createPackage("test.packageX", "authorityX", false)));
    358 
    359         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    360                 MockContactDirectoryProvider.class, "authority1");
    361 
    362         MatrixCursor response1 = provider1.createResponseCursor();
    363         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    364                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    365                 Directory.PHOTO_SUPPORT_NONE);
    366 
    367         MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider(
    368                 MockContactDirectoryProvider.class, "authority2");
    369 
    370         MatrixCursor response2 = provider2.createResponseCursor();
    371         addDirectoryRow(response2, "account-name2", "account-type2", "display-name2", 2,
    372                 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
    373                 Directory.PHOTO_SUPPORT_FULL);
    374 
    375         mDirectoryManager.scanAllPackages();
    376 
    377         // At this point the manager has discovered two custom directories.
    378         Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    379         assertEquals(4, cursor.getCount());
    380         cursor.close();
    381 
    382         // Pretend to rename the package name of a package on system update.
    383         PackageInfo info = mPackageManager.getInstalledPackages(0).get(1);
    384         info.packageName              = "test.package3";
    385         info.providers[0].packageName = "test.package3";
    386         MatrixCursor response3 = provider2.createResponseCursor();
    387         // Change resource id.
    388         addDirectoryRow(response3, "account-name2", "account-type2", "display-name2", 3,
    389                 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL,
    390                 Directory.PHOTO_SUPPORT_FULL);
    391 
    392         // When this happens on reboot, scanAllPackages() is called instead of onPackageChanged()
    393         // (as part of ContactsProvider2 initialization).
    394         // Accounts won't be affected so false should be passed here.
    395         mDirectoryManager.scanAllPackages(false);
    396 
    397         cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    398         // We should have columns for default, local_invisible, test.package1, and test.package3.
    399         // The row for test.package2 should not remain.
    400         assertEquals(4, cursor.getCount());
    401 
    402         cursor.moveToPosition(2);
    403         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1",
    404                 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    405                 Directory.PHOTO_SUPPORT_NONE);
    406 
    407         cursor.moveToNext();
    408         assertDirectoryRow(cursor, "test.package3", "authority2", "account-name2", "account-type2",
    409                 "display-name2", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY,
    410                 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
    411 
    412         cursor.close();
    413     }
    414 
    415     public void testAccountRemoval() throws Exception {
    416         mPackageManager.setInstalledPackages(
    417                 Lists.newArrayList(
    418                         createProviderPackage("test.package1", "authority1"),
    419                         createProviderPackage("test.package2", "authority2"),
    420                         createPackage("test.packageX", "authorityX", false)));
    421 
    422         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    423                 MockContactDirectoryProvider.class, "authority1");
    424 
    425         Account[] accounts = new Account[]{
    426                 new Account("account-name1", "account-type1"),
    427                 new Account("account-name2", "account-type2")};
    428         mActor.setAccounts(accounts);
    429         ((ContactsProvider2)getProvider()).onAccountsUpdated(accounts);
    430 
    431         MatrixCursor response1 = provider1.createResponseCursor();
    432         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    433                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    434                 Directory.PHOTO_SUPPORT_NONE);
    435         addDirectoryRow(response1, "account-name2", "account-type2", "display-name2", 2,
    436                 Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY,
    437                 Directory.PHOTO_SUPPORT_FULL_SIZE_ONLY);
    438 
    439         mDirectoryManager.scanAllPackages();
    440 
    441         accounts = new Account[]{new Account("account-name1", "account-type1")};
    442         mActor.setAccounts(accounts);
    443         ((ContactsProvider2)getProvider()).onAccountsUpdated(accounts);
    444 
    445         Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    446         assertEquals(3, cursor.getCount());
    447 
    448         cursor.moveToPosition(2);
    449         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1",
    450                 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    451                 Directory.PHOTO_SUPPORT_NONE);
    452 
    453         cursor.close();
    454     }
    455 
    456     public void testNotifyDirectoryChange() throws Exception {
    457         mPackageManager.setInstalledPackages(
    458                 Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
    459                         createPackage("test.packageX", "authorityX", false)));
    460 
    461         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    462                 MockContactDirectoryProvider.class, "authority1");
    463 
    464         MatrixCursor response1 = provider1.createResponseCursor();
    465         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    466                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    467                 Directory.PHOTO_SUPPORT_NONE);
    468 
    469         mDirectoryManager.scanAllPackages();
    470 
    471         // Pretend to replace the package with a different provider inside
    472         MatrixCursor response2 = provider1.createResponseCursor();
    473         addDirectoryRow(response2, "account-name2", "account-type2", "display-name2", 2,
    474                 Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_FULL,
    475                 Directory.PHOTO_SUPPORT_FULL);
    476 
    477         ContactsContract.Directory.notifyDirectoryChange(mResolver);
    478 
    479         Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null);
    480         assertEquals(3, cursor.getCount());
    481 
    482         cursor.moveToPosition(2);
    483         assertDirectoryRow(cursor, "test.package1", "authority1", "account-name2", "account-type2",
    484                 "display-name2", 2, Directory.EXPORT_SUPPORT_ANY_ACCOUNT,
    485                 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL);
    486 
    487         cursor.close();
    488     }
    489 
    490     public void testForwardingToDirectoryProvider() throws Exception {
    491         mPackageManager.setInstalledPackages(
    492                 Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
    493                         createPackage("test.packageX", "authorityX", false)));
    494 
    495         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    496                 MockContactDirectoryProvider.class, "authority1");
    497 
    498         MatrixCursor response1 = provider1.createResponseCursor();
    499         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    500                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    501                 Directory.PHOTO_SUPPORT_NONE);
    502 
    503         mDirectoryManager.scanAllPackages();
    504 
    505         Cursor cursor = mResolver.query(
    506                 Directory.CONTENT_URI, new String[] { Directory._ID }, null, null, null);
    507         cursor.moveToPosition(2);
    508         long directoryId = cursor.getLong(0);
    509         cursor.close();
    510 
    511         Uri contentUri = Contacts.CONTENT_URI.buildUpon().appendQueryParameter(
    512                 ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build();
    513 
    514         // The request should be forwarded to TestProvider, which will simply
    515         // package arguments and return them to us for verification
    516         cursor = mResolver.query(contentUri,
    517                 new String[]{"f1", "f2"}, "query", new String[]{"s1", "s2"}, "so");
    518         assertNotNull(cursor);
    519         assertEquals(1, cursor.getCount());
    520         cursor.moveToFirst();
    521         assertEquals("[f1, f2]", cursor.getString(cursor.getColumnIndex("projection")));
    522         assertEquals("query", cursor.getString(cursor.getColumnIndex("selection")));
    523         assertEquals("[s1, s2]", cursor.getString(cursor.getColumnIndex("selectionArgs")));
    524         assertEquals("so", cursor.getString(cursor.getColumnIndex("sortOrder")));
    525         assertEquals("account-name1", cursor.getString(cursor.getColumnIndex("accountName")));
    526         assertEquals("account-type1", cursor.getString(cursor.getColumnIndex("accountType")));
    527         cursor.close();
    528     }
    529 
    530     public void testProjectionPopulated() throws Exception {
    531         mPackageManager.setInstalledPackages(
    532                 Lists.newArrayList(createProviderPackage("test.package1", "authority1"),
    533                         createPackage("test.packageX", "authorityX", false)));
    534 
    535         MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider(
    536                 MockContactDirectoryProvider.class, "authority1");
    537 
    538         MatrixCursor response1 = provider1.createResponseCursor();
    539         addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1,
    540                 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE,
    541                 Directory.PHOTO_SUPPORT_NONE);
    542 
    543         mDirectoryManager.scanAllPackages();
    544 
    545         Cursor cursor = mResolver.query(
    546                 Directory.CONTENT_URI, new String[] { Directory._ID }, null, null, null);
    547         cursor.moveToPosition(2);
    548         long directoryId = cursor.getLong(0);
    549         cursor.close();
    550 
    551         Uri contentUri = AggregationExceptions.CONTENT_URI.buildUpon().appendQueryParameter(
    552                 ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build();
    553 
    554         // The request should be forwarded to TestProvider, which will return an empty cursor
    555         // but the projection should be correctly populated by ContactProvider
    556         assertProjection(contentUri, new String[]{
    557                 AggregationExceptionColumns._ID,
    558                 AggregationExceptions.TYPE,
    559                 AggregationExceptions.RAW_CONTACT_ID1,
    560                 AggregationExceptions.RAW_CONTACT_ID2,
    561         });
    562     }
    563 
    564     /**
    565      * Test {@link ContactDirectoryManager#getDirectoryProviderPackages} with the actual
    566      * package manager, and see if it returns the google sync package.
    567      */
    568     public void testGetDirectoryProviderPackages() {
    569         final PackageManager pm = getContext().getPackageManager();
    570         final String googleSync = "com.google.android.syncadapters.contacts";
    571 
    572         // Skip if the package is not installed.
    573         try {
    574             pm.getPackageInfo(googleSync, 0);
    575         } catch (NameNotFoundException e) {
    576             Log.w(TAG, googleSync + " not installed.  Skipping...");
    577             return;
    578         }
    579 
    580         // If installed, getDirectoryProviderPackages() should return it.
    581         assertTrue(ContactDirectoryManager.getDirectoryProviderPackages(pm).contains(googleSync));
    582     }
    583 
    584     protected PackageInfo createProviderPackage(String packageName, String authority) {
    585         return createPackage(packageName, authority, true);
    586     }
    587 
    588     protected PackageInfo createPackage(String packageName, String authority,
    589             boolean isDirectoryProvider) {
    590         PackageInfo providerPackage = new PackageInfo();
    591         providerPackage.packageName = packageName;
    592         ProviderInfo providerInfo = new ProviderInfo();
    593         providerInfo.packageName = providerPackage.packageName;
    594         providerInfo.authority = authority;
    595         if (isDirectoryProvider) {
    596             providerInfo.metaData = new Bundle();
    597             providerInfo.metaData.putBoolean("android.content.ContactDirectory", true);
    598         }
    599         providerPackage.providers = new ProviderInfo[] { providerInfo };
    600         return providerPackage;
    601     }
    602 
    603     protected void addDirectoryRow(MatrixCursor cursor, String accountName, String accountType,
    604             String displayName, int typeResourceId, int exportSupport, int shortcutSupport,
    605             int photoSupport) {
    606         Object[] row = new Object[cursor.getColumnCount()];
    607         row[cursor.getColumnIndex(Directory.ACCOUNT_NAME)] = accountName;
    608         row[cursor.getColumnIndex(Directory.ACCOUNT_TYPE)] = accountType;
    609         row[cursor.getColumnIndex(Directory.DISPLAY_NAME)] = displayName;
    610         row[cursor.getColumnIndex(Directory.TYPE_RESOURCE_ID)] = typeResourceId;
    611         row[cursor.getColumnIndex(Directory.EXPORT_SUPPORT)] = exportSupport;
    612         row[cursor.getColumnIndex(Directory.SHORTCUT_SUPPORT)] = shortcutSupport;
    613         row[cursor.getColumnIndex(Directory.PHOTO_SUPPORT)] = photoSupport;
    614         cursor.addRow(row);
    615     }
    616 
    617     protected void assertDirectoryRow(Cursor cursor, String packageName, String authority,
    618             String accountName, String accountType, String displayName, int typeResourceId,
    619             int exportSupport, int shortcutSupport, int photoSupport) {
    620         ContentValues values = new ContentValues();
    621         values.put(Directory.PACKAGE_NAME, packageName);
    622         values.put(Directory.DIRECTORY_AUTHORITY, authority);
    623         values.put(Directory.ACCOUNT_NAME, accountName);
    624         values.put(Directory.ACCOUNT_TYPE, accountType);
    625         values.put(Directory.DISPLAY_NAME, displayName);
    626         values.put(Directory.TYPE_RESOURCE_ID, typeResourceId);
    627         values.put(Directory.EXPORT_SUPPORT, exportSupport);
    628         values.put(Directory.SHORTCUT_SUPPORT, shortcutSupport);
    629         values.put(Directory.PHOTO_SUPPORT, photoSupport);
    630 
    631         assertCursorValues(cursor, values);
    632     }
    633 }
    634