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 attachInfo(Context context, ProviderInfo info)66 public void attachInfo(Context context, ProviderInfo info) { 67 mAuthority = info.authority; 68 } 69 createResponseCursor()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 query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)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 setUp()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 testIsDirectoryProvider()122 public void testIsDirectoryProvider() { 123 ProviderInfo provider = new ProviderInfo(); 124 125 // No metadata 126 assertFalse(ContactDirectoryManager.isDirectoryProvider(provider)); 127 128 // No CONTACT_DIRECTORY_META_DATA 129 provider.metaData = new Bundle(); 130 assertFalse(ContactDirectoryManager.isDirectoryProvider(provider)); 131 132 // CONTACT_DIRECTORY_META_DATA is a string 133 provider.metaData.putString("android.content.ContactDirectory", ""); 134 assertFalse(ContactDirectoryManager.isDirectoryProvider(provider)); 135 136 // CONTACT_DIRECTORY_META_DATA is false 137 provider.metaData.putBoolean("android.content.ContactDirectory", false); 138 assertFalse(ContactDirectoryManager.isDirectoryProvider(provider)); 139 140 // CONTACT_DIRECTORY_META_DATA is true 141 provider.metaData.putBoolean("android.content.ContactDirectory", true); 142 assertTrue(ContactDirectoryManager.isDirectoryProvider(provider)); 143 } 144 testScanAllProviders()145 public void testScanAllProviders() throws Exception { 146 mPackageManager.setInstalledPackages( 147 Lists.newArrayList( 148 createProviderPackage("test.package1", "authority1"), 149 createProviderPackage("test.package2", "authority2"), 150 createPackage("test.packageX", "authorityX", false))); 151 152 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 153 MockContactDirectoryProvider.class, "authority1"); 154 155 MatrixCursor response1 = provider1.createResponseCursor(); 156 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 157 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 158 Directory.PHOTO_SUPPORT_FULL_SIZE_ONLY); 159 addDirectoryRow(response1, "account-name2", "account-type2", "display-name2", 2, 160 Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY, 161 Directory.PHOTO_SUPPORT_THUMBNAIL_ONLY); 162 163 MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( 164 MockContactDirectoryProvider.class, "authority2"); 165 166 MatrixCursor response2 = provider2.createResponseCursor(); 167 addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, 168 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL, 169 Directory.PHOTO_SUPPORT_FULL); 170 171 mDirectoryManager.scanAllPackages(); 172 173 Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 174 assertEquals(5, cursor.getCount()); 175 176 cursor.moveToPosition(2); 177 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", 178 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 179 Directory.PHOTO_SUPPORT_FULL_SIZE_ONLY); 180 181 cursor.moveToNext(); 182 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name2", "account-type2", 183 "display-name2", 2, Directory.EXPORT_SUPPORT_ANY_ACCOUNT, 184 Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY, Directory.PHOTO_SUPPORT_THUMBNAIL_ONLY); 185 186 cursor.moveToNext(); 187 assertDirectoryRow(cursor, "test.package2", "authority2", "account-name3", "account-type3", 188 "display-name3", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, 189 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL); 190 191 cursor.close(); 192 } 193 testPackageInstalled()194 public void testPackageInstalled() throws Exception { 195 mPackageManager.setInstalledPackages( 196 Lists.newArrayList(createProviderPackage("test.package1", "authority1"), 197 createPackage("test.packageX", "authorityX", false))); 198 199 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 200 MockContactDirectoryProvider.class, "authority1"); 201 202 MatrixCursor response1 = provider1.createResponseCursor(); 203 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 204 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 205 Directory.PHOTO_SUPPORT_FULL); 206 207 mDirectoryManager.scanAllPackages(); 208 209 // At this point the manager has discovered a single directory (plus two 210 // standard ones). 211 Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 212 assertEquals(3, cursor.getCount()); 213 cursor.close(); 214 215 // Pretend to install another package 216 MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( 217 MockContactDirectoryProvider.class, "authority2"); 218 219 MatrixCursor response2 = provider2.createResponseCursor(); 220 addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, 221 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL, 222 Directory.PHOTO_SUPPORT_FULL); 223 224 mPackageManager.getInstalledPackages(0).add( 225 createProviderPackage("test.package2", "authority2")); 226 227 mProvider.onPackageChanged("test.package2"); 228 229 cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 230 assertEquals(4, cursor.getCount()); 231 232 cursor.moveToPosition(2); 233 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", 234 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 235 Directory.PHOTO_SUPPORT_FULL); 236 237 cursor.moveToNext(); 238 assertDirectoryRow(cursor, "test.package2", "authority2", "account-name3", "account-type3", 239 "display-name3", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, 240 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL); 241 242 cursor.close(); 243 } 244 testPackageUninstalled()245 public void testPackageUninstalled() throws Exception { 246 mPackageManager.setInstalledPackages( 247 Lists.newArrayList( 248 createProviderPackage("test.package1", "authority1"), 249 createProviderPackage("test.package2", "authority2"), 250 createPackage("test.packageX", "authorityX", false))); 251 252 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 253 MockContactDirectoryProvider.class, "authority1"); 254 255 MatrixCursor response1 = provider1.createResponseCursor(); 256 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 257 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 258 Directory.PHOTO_SUPPORT_NONE); 259 260 MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( 261 MockContactDirectoryProvider.class, "authority2"); 262 263 MatrixCursor response2 = provider2.createResponseCursor(); 264 addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, 265 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL, 266 Directory.PHOTO_SUPPORT_FULL); 267 268 mDirectoryManager.scanAllPackages(); 269 270 // At this point the manager has discovered two custom directories. 271 Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 272 assertEquals(4, cursor.getCount()); 273 cursor.close(); 274 275 // Pretend to uninstall one of the packages 276 mPackageManager.getInstalledPackages(0).remove(1); 277 278 mProvider.onPackageChanged("test.package2"); 279 280 cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 281 assertEquals(3, cursor.getCount()); 282 283 cursor.moveToPosition(2); 284 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", 285 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 286 Directory.PHOTO_SUPPORT_NONE); 287 288 cursor.close(); 289 } 290 testPackageReplaced()291 public void testPackageReplaced() throws Exception { 292 mPackageManager.setInstalledPackages( 293 Lists.newArrayList( 294 createProviderPackage("test.package1", "authority1"), 295 createProviderPackage("test.package2", "authority2"), 296 createPackage("test.packageX", "authorityX", false))); 297 298 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 299 MockContactDirectoryProvider.class, "authority1"); 300 301 MatrixCursor response1 = provider1.createResponseCursor(); 302 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 303 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 304 Directory.PHOTO_SUPPORT_NONE); 305 306 MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( 307 MockContactDirectoryProvider.class, "authority2"); 308 309 MatrixCursor response2 = provider2.createResponseCursor(); 310 addDirectoryRow(response2, "account-name3", "account-type3", "display-name3", 3, 311 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL, 312 Directory.PHOTO_SUPPORT_FULL); 313 314 mDirectoryManager.scanAllPackages(); 315 316 // At this point the manager has discovered two custom directories. 317 Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 318 assertEquals(4, cursor.getCount()); 319 cursor.close(); 320 321 // Pretend to replace the package with a different provider inside 322 MatrixCursor response3 = provider2.createResponseCursor(); 323 addDirectoryRow(response3, "account-name4", "account-type4", "display-name4", 4, 324 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 325 Directory.PHOTO_SUPPORT_NONE); 326 327 mProvider.onPackageChanged("test.package2"); 328 329 cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 330 assertEquals(4, cursor.getCount()); 331 332 cursor.moveToPosition(2); 333 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", 334 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 335 Directory.PHOTO_SUPPORT_NONE); 336 337 cursor.moveToNext(); 338 assertDirectoryRow(cursor, "test.package2", "authority2", "account-name4", "account-type4", 339 "display-name4", 4, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 340 Directory.PHOTO_SUPPORT_NONE); 341 342 cursor.close(); 343 } 344 345 /** 346 * Tests if the manager works correctly when the package name for a directory is changed 347 * (on system update). 348 */ testPackageRenamed()349 public void testPackageRenamed() throws Exception { 350 mPackageManager.setInstalledPackages( 351 Lists.newArrayList( 352 createProviderPackage("test.package1", "authority1"), 353 createProviderPackage("test.package2", "authority2"), 354 createPackage("test.packageX", "authorityX", false))); 355 356 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 357 MockContactDirectoryProvider.class, "authority1"); 358 359 MatrixCursor response1 = provider1.createResponseCursor(); 360 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 361 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 362 Directory.PHOTO_SUPPORT_NONE); 363 364 MockContactDirectoryProvider provider2 = (MockContactDirectoryProvider) addProvider( 365 MockContactDirectoryProvider.class, "authority2"); 366 367 MatrixCursor response2 = provider2.createResponseCursor(); 368 addDirectoryRow(response2, "account-name2", "account-type2", "display-name2", 2, 369 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL, 370 Directory.PHOTO_SUPPORT_FULL); 371 372 mDirectoryManager.scanAllPackages(); 373 374 // At this point the manager has discovered two custom directories. 375 Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 376 assertEquals(4, cursor.getCount()); 377 cursor.close(); 378 379 // Pretend to rename the package name of a package on system update. 380 PackageInfo info = mPackageManager.getInstalledPackages(0).get(1); 381 info.packageName = "test.package3"; 382 info.providers[0].packageName = "test.package3"; 383 MatrixCursor response3 = provider2.createResponseCursor(); 384 // Change resource id. 385 addDirectoryRow(response3, "account-name2", "account-type2", "display-name2", 3, 386 Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, Directory.SHORTCUT_SUPPORT_FULL, 387 Directory.PHOTO_SUPPORT_FULL); 388 389 // When this happens on reboot, scanAllPackages() is called instead of onPackageChanged() 390 // (as part of ContactsProvider2 initialization). 391 // Accounts won't be affected so false should be passed here. 392 mDirectoryManager.scanAllPackages(false); 393 394 cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 395 // We should have columns for default, local_invisible, test.package1, and test.package3. 396 // The row for test.package2 should not remain. 397 assertEquals(4, cursor.getCount()); 398 399 cursor.moveToPosition(2); 400 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", 401 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 402 Directory.PHOTO_SUPPORT_NONE); 403 404 cursor.moveToNext(); 405 assertDirectoryRow(cursor, "test.package3", "authority2", "account-name2", "account-type2", 406 "display-name2", 3, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY, 407 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL); 408 409 cursor.close(); 410 } 411 testAccountRemoval()412 public void testAccountRemoval() throws Exception { 413 mPackageManager.setInstalledPackages( 414 Lists.newArrayList( 415 createProviderPackage("test.package1", "authority1"), 416 createProviderPackage("test.package2", "authority2"), 417 createPackage("test.packageX", "authorityX", false))); 418 419 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 420 MockContactDirectoryProvider.class, "authority1"); 421 422 Account[] accounts = new Account[]{ 423 new Account("account-name1", "account-type1"), 424 new Account("account-name2", "account-type2")}; 425 mActor.setAccounts(accounts); 426 ((ContactsProvider2)getProvider()).onAccountsUpdated(accounts); 427 428 MatrixCursor response1 = provider1.createResponseCursor(); 429 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 430 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 431 Directory.PHOTO_SUPPORT_NONE); 432 addDirectoryRow(response1, "account-name2", "account-type2", "display-name2", 2, 433 Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_DATA_ITEMS_ONLY, 434 Directory.PHOTO_SUPPORT_FULL_SIZE_ONLY); 435 436 mDirectoryManager.scanAllPackages(); 437 438 accounts = new Account[]{new Account("account-name1", "account-type1")}; 439 mActor.setAccounts(accounts); 440 ((ContactsProvider2)getProvider()).onAccountsUpdated(accounts); 441 442 Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 443 assertEquals(3, cursor.getCount()); 444 445 cursor.moveToPosition(2); 446 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name1", "account-type1", 447 "display-name1", 1, Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 448 Directory.PHOTO_SUPPORT_NONE); 449 450 cursor.close(); 451 } 452 testNotifyDirectoryChange()453 public void testNotifyDirectoryChange() throws Exception { 454 mPackageManager.setInstalledPackages( 455 Lists.newArrayList(createProviderPackage("test.package1", "authority1"), 456 createPackage("test.packageX", "authorityX", false))); 457 458 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 459 MockContactDirectoryProvider.class, "authority1"); 460 461 MatrixCursor response1 = provider1.createResponseCursor(); 462 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 463 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 464 Directory.PHOTO_SUPPORT_NONE); 465 466 mDirectoryManager.scanAllPackages(); 467 468 // Pretend to replace the package with a different provider inside 469 MatrixCursor response2 = provider1.createResponseCursor(); 470 addDirectoryRow(response2, "account-name2", "account-type2", "display-name2", 2, 471 Directory.EXPORT_SUPPORT_ANY_ACCOUNT, Directory.SHORTCUT_SUPPORT_FULL, 472 Directory.PHOTO_SUPPORT_FULL); 473 474 ContactsContract.Directory.notifyDirectoryChange(mResolver); 475 476 Cursor cursor = mResolver.query(Directory.CONTENT_URI, null, null, null, null); 477 assertEquals(3, cursor.getCount()); 478 479 cursor.moveToPosition(2); 480 assertDirectoryRow(cursor, "test.package1", "authority1", "account-name2", "account-type2", 481 "display-name2", 2, Directory.EXPORT_SUPPORT_ANY_ACCOUNT, 482 Directory.SHORTCUT_SUPPORT_FULL, Directory.PHOTO_SUPPORT_FULL); 483 484 cursor.close(); 485 } 486 testForwardingToDirectoryProvider()487 public void testForwardingToDirectoryProvider() throws Exception { 488 mPackageManager.setInstalledPackages( 489 Lists.newArrayList(createProviderPackage("test.package1", "authority1"), 490 createPackage("test.packageX", "authorityX", false))); 491 492 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 493 MockContactDirectoryProvider.class, "authority1"); 494 495 MatrixCursor response1 = provider1.createResponseCursor(); 496 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 497 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 498 Directory.PHOTO_SUPPORT_NONE); 499 500 mDirectoryManager.scanAllPackages(); 501 502 Cursor cursor = mResolver.query( 503 Directory.CONTENT_URI, new String[] { Directory._ID }, null, null, null); 504 cursor.moveToPosition(2); 505 long directoryId = cursor.getLong(0); 506 cursor.close(); 507 508 Uri contentUri = Contacts.CONTENT_URI.buildUpon().appendQueryParameter( 509 ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build(); 510 511 // The request should be forwarded to TestProvider, which will simply 512 // package arguments and return them to us for verification 513 cursor = mResolver.query(contentUri, 514 new String[]{"f1", "f2"}, "query", new String[]{"s1", "s2"}, "so"); 515 assertNotNull(cursor); 516 assertEquals(1, cursor.getCount()); 517 cursor.moveToFirst(); 518 assertEquals("[f1, f2]", cursor.getString(cursor.getColumnIndex("projection"))); 519 assertEquals("query", cursor.getString(cursor.getColumnIndex("selection"))); 520 assertEquals("[s1, s2]", cursor.getString(cursor.getColumnIndex("selectionArgs"))); 521 assertEquals("so", cursor.getString(cursor.getColumnIndex("sortOrder"))); 522 assertEquals("account-name1", cursor.getString(cursor.getColumnIndex("accountName"))); 523 assertEquals("account-type1", cursor.getString(cursor.getColumnIndex("accountType"))); 524 cursor.close(); 525 } 526 testProjectionPopulated()527 public void testProjectionPopulated() throws Exception { 528 mPackageManager.setInstalledPackages( 529 Lists.newArrayList(createProviderPackage("test.package1", "authority1"), 530 createPackage("test.packageX", "authorityX", false))); 531 532 MockContactDirectoryProvider provider1 = (MockContactDirectoryProvider) addProvider( 533 MockContactDirectoryProvider.class, "authority1"); 534 535 MatrixCursor response1 = provider1.createResponseCursor(); 536 addDirectoryRow(response1, "account-name1", "account-type1", "display-name1", 1, 537 Directory.EXPORT_SUPPORT_NONE, Directory.SHORTCUT_SUPPORT_NONE, 538 Directory.PHOTO_SUPPORT_NONE); 539 540 mDirectoryManager.scanAllPackages(); 541 542 Cursor cursor = mResolver.query( 543 Directory.CONTENT_URI, new String[] { Directory._ID }, null, null, null); 544 cursor.moveToPosition(2); 545 long directoryId = cursor.getLong(0); 546 cursor.close(); 547 548 Uri contentUri = AggregationExceptions.CONTENT_URI.buildUpon().appendQueryParameter( 549 ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build(); 550 551 // The request should be forwarded to TestProvider, which will return an empty cursor 552 // but the projection should be correctly populated by ContactProvider 553 assertProjection(contentUri, new String[]{ 554 AggregationExceptionColumns._ID, 555 AggregationExceptions.TYPE, 556 AggregationExceptions.RAW_CONTACT_ID1, 557 AggregationExceptions.RAW_CONTACT_ID2, 558 }); 559 } 560 561 /** 562 * Test {@link ContactDirectoryManager#getDirectoryProviderPackages} with the actual 563 * package manager, and see if it returns the google sync package. 564 */ testGetDirectoryProviderPackages()565 public void testGetDirectoryProviderPackages() { 566 final PackageManager pm = getContext().getPackageManager(); 567 final String googleSync = "com.google.android.syncadapters.contacts"; 568 569 // Skip if the package is not installed. 570 try { 571 pm.getPackageInfo(googleSync, 0); 572 } catch (NameNotFoundException e) { 573 Log.w(TAG, googleSync + " not installed. Skipping..."); 574 return; 575 } 576 577 // If installed, getDirectoryProviderPackages() should return it. 578 assertTrue(ContactDirectoryManager.getDirectoryProviderPackages(pm).contains(googleSync)); 579 } 580 createProviderPackage(String packageName, String authority)581 protected PackageInfo createProviderPackage(String packageName, String authority) { 582 return createPackage(packageName, authority, true); 583 } 584 createPackage(String packageName, String authority, boolean isDirectoryProvider)585 protected PackageInfo createPackage(String packageName, String authority, 586 boolean isDirectoryProvider) { 587 PackageInfo providerPackage = new PackageInfo(); 588 providerPackage.packageName = packageName; 589 ProviderInfo providerInfo = new ProviderInfo(); 590 providerInfo.packageName = providerPackage.packageName; 591 providerInfo.authority = authority; 592 if (isDirectoryProvider) { 593 providerInfo.metaData = new Bundle(); 594 providerInfo.metaData.putBoolean("android.content.ContactDirectory", true); 595 } 596 providerPackage.providers = new ProviderInfo[] { providerInfo }; 597 return providerPackage; 598 } 599 addDirectoryRow(MatrixCursor cursor, String accountName, String accountType, String displayName, int typeResourceId, int exportSupport, int shortcutSupport, int photoSupport)600 protected void addDirectoryRow(MatrixCursor cursor, String accountName, String accountType, 601 String displayName, int typeResourceId, int exportSupport, int shortcutSupport, 602 int photoSupport) { 603 Object[] row = new Object[cursor.getColumnCount()]; 604 row[cursor.getColumnIndex(Directory.ACCOUNT_NAME)] = accountName; 605 row[cursor.getColumnIndex(Directory.ACCOUNT_TYPE)] = accountType; 606 row[cursor.getColumnIndex(Directory.DISPLAY_NAME)] = displayName; 607 row[cursor.getColumnIndex(Directory.TYPE_RESOURCE_ID)] = typeResourceId; 608 row[cursor.getColumnIndex(Directory.EXPORT_SUPPORT)] = exportSupport; 609 row[cursor.getColumnIndex(Directory.SHORTCUT_SUPPORT)] = shortcutSupport; 610 row[cursor.getColumnIndex(Directory.PHOTO_SUPPORT)] = photoSupport; 611 cursor.addRow(row); 612 } 613 assertDirectoryRow(Cursor cursor, String packageName, String authority, String accountName, String accountType, String displayName, int typeResourceId, int exportSupport, int shortcutSupport, int photoSupport)614 protected void assertDirectoryRow(Cursor cursor, String packageName, String authority, 615 String accountName, String accountType, String displayName, int typeResourceId, 616 int exportSupport, int shortcutSupport, int photoSupport) { 617 ContentValues values = new ContentValues(); 618 values.put(Directory.PACKAGE_NAME, packageName); 619 values.put(Directory.DIRECTORY_AUTHORITY, authority); 620 values.put(Directory.ACCOUNT_NAME, accountName); 621 values.put(Directory.ACCOUNT_TYPE, accountType); 622 values.put(Directory.DISPLAY_NAME, displayName); 623 values.put(Directory.TYPE_RESOURCE_ID, typeResourceId); 624 values.put(Directory.EXPORT_SUPPORT, exportSupport); 625 values.put(Directory.SHORTCUT_SUPPORT, shortcutSupport); 626 values.put(Directory.PHOTO_SUPPORT, photoSupport); 627 628 assertCursorValues(cursor, values); 629 } 630 } 631