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 17package com.android.providers.contacts; 18 19import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns; 20import com.google.android.collect.Lists; 21 22import android.accounts.Account; 23import android.content.ContentValues; 24import android.content.Context; 25import android.content.pm.PackageInfo; 26import android.content.pm.PackageManager; 27import android.content.pm.PackageManager.NameNotFoundException; 28import android.content.pm.ProviderInfo; 29import android.database.Cursor; 30import android.database.MatrixCursor; 31import android.net.Uri; 32import android.os.Bundle; 33import android.provider.ContactsContract; 34import android.provider.ContactsContract.AggregationExceptions; 35import android.provider.ContactsContract.Contacts; 36import android.provider.ContactsContract.Directory; 37import android.provider.ContactsContract.RawContacts; 38import android.test.mock.MockContentProvider; 39import android.test.suitebuilder.annotation.MediumTest; 40import android.util.Log; 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 50public 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 attachInfo(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 // 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 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 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 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 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 */ 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 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 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 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 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 */ 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 581 protected PackageInfo createProviderPackage(String packageName, String authority) { 582 return createPackage(packageName, authority, true); 583 } 584 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 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 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