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