1 /* 2 * Copyright (C) 2016 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 package com.android.providers.blockednumber; 17 18 import static org.mockito.Matchers.anyInt; 19 import static org.mockito.Matchers.anyString; 20 import static org.mockito.Matchers.eq; 21 import static org.mockito.Mockito.doReturn; 22 import static org.mockito.Mockito.reset; 23 import static org.mockito.Mockito.spy; 24 import static org.mockito.Mockito.times; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.when; 27 28 import android.app.AppOpsManager; 29 import android.content.ContentResolver; 30 import android.content.ContentUris; 31 import android.content.ContentValues; 32 import android.content.pm.PackageManager; 33 import android.database.ContentObserver; 34 import android.database.Cursor; 35 import android.database.sqlite.SQLiteException; 36 import android.location.Country; 37 import android.net.Uri; 38 import android.os.Bundle; 39 import android.os.PersistableBundle; 40 import android.os.SystemProperties; 41 import android.provider.BlockedNumberContract; 42 import android.provider.BlockedNumberContract.BlockedNumbers; 43 import android.provider.BlockedNumberContract.SystemContract; 44 import android.telecom.TelecomManager; 45 import android.telephony.CarrierConfigManager; 46 import android.telephony.TelephonyManager; 47 import android.test.AndroidTestCase; 48 import android.test.MoreAsserts; 49 import android.test.suitebuilder.annotation.MediumTest; 50 51 import junit.framework.Assert; 52 53 import java.util.concurrent.CountDownLatch; 54 import java.util.concurrent.TimeUnit; 55 56 /** 57 * runtest --path packages/providers/BlockedNumberProvider/tests 58 */ 59 @MediumTest 60 public class BlockedNumberProviderTest extends AndroidTestCase { 61 private MyMockContext mMockContext; 62 private ContentResolver mResolver; 63 64 @Override setUp()65 protected void setUp() throws Exception { 66 super.setUp(); 67 BlockedNumberProvider.ALLOW_SELF_CALL = false; 68 69 mMockContext = spy(new MyMockContext(getContext())); 70 mMockContext.initializeContext(); 71 mResolver = mMockContext.getContentResolver(); 72 73 when(mMockContext.mUserManager.isPrimaryUser()).thenReturn(true); 74 when(mMockContext.mCountryDetector.detectCountry()) 75 .thenReturn(new Country("US", Country.COUNTRY_SOURCE_LOCATION)); 76 when(mMockContext.mAppOpsManager.noteOp( 77 eq(AppOpsManager.OP_WRITE_SMS), anyInt(), anyString())) 78 .thenReturn(AppOpsManager.MODE_ERRORED); 79 } 80 81 @Override tearDown()82 protected void tearDown() throws Exception { 83 mMockContext.shutdown(); 84 85 super.tearDown(); 86 } 87 cv(Object... namesAndValues)88 private static ContentValues cv(Object... namesAndValues) { 89 Assert.assertTrue((namesAndValues.length % 2) == 0); 90 91 final ContentValues ret = new ContentValues(); 92 for (int i = 1; i < namesAndValues.length; i += 2) { 93 final String name = namesAndValues[i - 1].toString(); 94 final Object value = namesAndValues[i]; 95 if (value == null) { 96 ret.putNull(name); 97 } else if (value instanceof String) { 98 ret.put(name, (String) value); 99 } else if (value instanceof Integer) { 100 ret.put(name, (Integer) value); 101 } else if (value instanceof Long) { 102 ret.put(name, (Long) value); 103 } else { 104 Assert.fail("Unsupported type: " + value.getClass().getSimpleName()); 105 } 106 } 107 return ret; 108 } 109 assertRowCount(int count, Uri uri)110 private void assertRowCount(int count, Uri uri) { 111 try (Cursor c = mResolver.query(uri, null, null, null, null)) { 112 assertEquals(count, c.getCount()); 113 } 114 } 115 testGetType()116 public void testGetType() { 117 assertEquals(BlockedNumbers.CONTENT_TYPE, mResolver.getType( 118 BlockedNumbers.CONTENT_URI)); 119 120 assertEquals(BlockedNumbers.CONTENT_ITEM_TYPE, mResolver.getType( 121 ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, 1))); 122 123 assertNull(mResolver.getType( 124 Uri.withAppendedPath(BlockedNumberContract.AUTHORITY_URI, "invalid"))); 125 } 126 testInsert()127 public void testInsert() { 128 insertExpectingFailure(cv()); 129 insertExpectingFailure(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, null)); 130 insertExpectingFailure(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "")); 131 insertExpectingFailure(cv(BlockedNumbers.COLUMN_ID, 1)); 132 insertExpectingFailure(cv(BlockedNumbers.COLUMN_E164_NUMBER, "1")); 133 134 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 135 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "+1-2-3")); 136 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "+1-408-454-1111")); 137 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1-408-454-2222")); 138 // Re-inserting the same number should be ok, but the E164 number is replaced. 139 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1-408-454-2222", 140 BlockedNumbers.COLUMN_E164_NUMBER, "+814084542222")); 141 142 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1-408-4542222")); 143 144 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "045-381-1111", 145 BlockedNumbers.COLUMN_E164_NUMBER, "+81453811111")); 146 147 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "12345")); 148 149 150 151 assertRowCount(7, BlockedNumbers.CONTENT_URI); 152 153 assertContents(1, "123", ""); 154 assertContents(2, "+1-2-3", ""); 155 assertContents(3, "+1-408-454-1111", "+14084541111"); 156 // Missing 4 due to re-insertion of the same number. 157 assertContents(5, "1-408-454-2222", "+814084542222"); 158 assertContents(6, "1-408-4542222", "+14084542222"); 159 assertContents(7, "045-381-1111", "+81453811111"); 160 assertContents(8, "12345", ""); 161 } 162 testChangesNotified()163 public void testChangesNotified() throws Exception { 164 Cursor c = mResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 165 166 final CountDownLatch latch = new CountDownLatch(2); 167 ContentObserver contentObserver = new ContentObserver(null) { 168 @Override 169 public void onChange(boolean selfChange) { 170 Assert.assertFalse(selfChange); 171 latch.notify(); 172 } 173 }; 174 c.registerContentObserver(contentObserver); 175 176 try { 177 Uri uri = insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "14506507000")); 178 mResolver.delete(uri, null, null); 179 latch.await(10, TimeUnit.SECONDS); 180 verify(mMockContext.mBackupManager, times(2)).dataChanged(); 181 } catch (Exception e) { 182 fail(e.toString()); 183 } finally { 184 c.unregisterContentObserver(contentObserver); 185 } 186 } 187 insert(ContentValues cv)188 private Uri insert(ContentValues cv) { 189 final Uri uri = mResolver.insert(BlockedNumbers.CONTENT_URI, cv); 190 assertNotNull(uri); 191 192 // Make sure the URI exists. 193 try (Cursor c = mResolver.query(uri, null, null, null, null)) { 194 assertEquals(1, c.getCount()); 195 } 196 return uri; 197 } 198 insertExpectingFailure(ContentValues cv)199 private void insertExpectingFailure(ContentValues cv) { 200 try { 201 mResolver.insert( 202 BlockedNumbers.CONTENT_URI, cv); 203 fail(); 204 } catch (IllegalArgumentException expected) { 205 } 206 } 207 testDelete()208 public void testDelete() { 209 // Prepare test data 210 Uri u1 = insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 211 Uri u2 = insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "+1-2-3")); 212 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "+1-408-454-1111")); 213 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1-408-454-2222")); 214 215 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "045-381-1111", 216 BlockedNumbers.COLUMN_E164_NUMBER, "12345")); 217 218 assertRowCount(5, BlockedNumbers.CONTENT_URI); 219 220 // Delete and check the # of remaining rows. 221 222 mResolver.delete(u1, null, null); 223 assertRowCount(4, BlockedNumbers.CONTENT_URI); 224 225 try { 226 mResolver.delete(u2, "1=1", null); 227 fail(); 228 } catch (IllegalArgumentException expected) { 229 MoreAsserts.assertContainsRegex("selection must be null", expected.getMessage()); 230 } 231 232 mResolver.delete(u2, null, null); 233 assertRowCount(3, BlockedNumbers.CONTENT_URI); 234 235 mResolver.delete(BlockedNumbers.CONTENT_URI, 236 BlockedNumbers.COLUMN_E164_NUMBER + "=?", 237 new String[]{"12345"}); 238 assertRowCount(2, BlockedNumbers.CONTENT_URI); 239 240 // SQL injection should be detected. 241 try { 242 mResolver.delete(BlockedNumbers.CONTENT_URI, "; DROP TABLE blocked; ", null); 243 fail(); 244 } catch (SQLiteException expected) { 245 } 246 assertRowCount(2, BlockedNumbers.CONTENT_URI); 247 248 mResolver.delete(BlockedNumbers.CONTENT_URI, null, null); 249 assertRowCount(0, BlockedNumbers.CONTENT_URI); 250 } 251 testUpdate()252 public void testUpdate() { 253 try { 254 mResolver.update(BlockedNumbers.CONTENT_URI, cv(), 255 /* selection =*/ null, /* args =*/ null); 256 fail(); 257 } catch (UnsupportedOperationException expected) { 258 MoreAsserts.assertContainsRegex("Update is not supported", expected.getMessage()); 259 } 260 } 261 testBlockSuppressionAfterEmergencyContact()262 public void testBlockSuppressionAfterEmergencyContact() { 263 int blockSuppressionSeconds = 1000; 264 when(mMockContext.mCarrierConfigManager.getConfig()) 265 .thenReturn(getBundleWithInt(blockSuppressionSeconds)); 266 267 String phoneNumber = "5004541111"; 268 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, phoneNumber)); 269 270 // No emergency contact: Blocks should not be suppressed. 271 assertIsBlocked(true, phoneNumber); 272 assertShouldSystemBlock(true, phoneNumber, null); 273 verifyBlocksNotSuppressed(); 274 assertTrue(mMockContext.mIntentsBroadcasted.isEmpty()); 275 276 // No emergency contact yet: Ending block suppression should be a no-op. 277 SystemContract.endBlockSuppression(mMockContext); 278 assertIsBlocked(true, phoneNumber); 279 assertShouldSystemBlock(true, phoneNumber, null); 280 verifyBlocksNotSuppressed(); 281 assertTrue(mMockContext.mIntentsBroadcasted.isEmpty()); 282 283 // After emergency contact blocks should be suppressed. 284 long timestampMillisBeforeEmergencyContact = System.currentTimeMillis(); 285 SystemContract.notifyEmergencyContact(mMockContext); 286 assertIsBlocked(true, phoneNumber); 287 assertShouldSystemBlock(false, phoneNumber, null); 288 SystemContract.BlockSuppressionStatus status = 289 SystemContract.getBlockSuppressionStatus(mMockContext); 290 assertTrue(status.isSuppressed); 291 assertValidBlockSuppressionExpiration(timestampMillisBeforeEmergencyContact, 292 blockSuppressionSeconds, status.untilTimestampMillis); 293 assertEquals(1, mMockContext.mIntentsBroadcasted.size()); 294 assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, 295 mMockContext.mIntentsBroadcasted.get(0)); 296 mMockContext.mIntentsBroadcasted.clear(); 297 298 // Ending block suppression should work. 299 SystemContract.endBlockSuppression(mMockContext); 300 assertIsBlocked(true, phoneNumber); 301 assertShouldSystemBlock(true, phoneNumber, null); 302 verifyBlocksNotSuppressed(); 303 assertEquals(1, mMockContext.mIntentsBroadcasted.size()); 304 assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, 305 mMockContext.mIntentsBroadcasted.get(0)); 306 } 307 testBlockSuppressionAfterEmergencyContact_invalidCarrierConfigDefaultValueUsed()308 public void testBlockSuppressionAfterEmergencyContact_invalidCarrierConfigDefaultValueUsed() { 309 int invalidBlockSuppressionSeconds = 700000; // > 1 week 310 when(mMockContext.mCarrierConfigManager.getConfig()) 311 .thenReturn(getBundleWithInt(invalidBlockSuppressionSeconds)); 312 313 String phoneNumber = "5004541111"; 314 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, phoneNumber)); 315 316 long timestampMillisBeforeEmergencyContact = System.currentTimeMillis(); 317 SystemContract.notifyEmergencyContact(mMockContext); 318 assertIsBlocked(true, phoneNumber); 319 assertShouldSystemBlock(false, phoneNumber, null); 320 SystemContract.BlockSuppressionStatus status = 321 SystemContract.getBlockSuppressionStatus(mMockContext); 322 assertTrue(status.isSuppressed); 323 assertValidBlockSuppressionExpiration(timestampMillisBeforeEmergencyContact, 324 7200 /* Default value of 2 hours */, status.untilTimestampMillis); 325 assertEquals(1, mMockContext.mIntentsBroadcasted.size()); 326 assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, 327 mMockContext.mIntentsBroadcasted.get(0)); 328 } 329 testEnhancedBlock()330 public void testEnhancedBlock() { 331 String phoneNumber = "5004541111"; 332 333 // Check whether block numbers not in contacts setting works well 334 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, true); 335 assertShouldSystemBlock(true, phoneNumber, 336 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); 337 assertShouldSystemBlock(false, phoneNumber, 338 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, true)); 339 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, false); 340 assertShouldSystemBlock(false, phoneNumber, 341 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); 342 343 // Check whether block private number calls setting works well 344 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, true); 345 assertShouldSystemBlock(true, phoneNumber, 346 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); 347 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, false); 348 assertShouldSystemBlock(false, phoneNumber, 349 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); 350 351 // Check whether block payphone calls setting works well 352 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, true); 353 assertShouldSystemBlock(true, phoneNumber, 354 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); 355 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, false); 356 assertShouldSystemBlock(false, phoneNumber, 357 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); 358 359 // Check whether block unknown calls setting works well 360 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, true); 361 assertShouldSystemBlock(true, phoneNumber, 362 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); 363 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, false); 364 assertShouldSystemBlock(false, phoneNumber, 365 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); 366 } 367 testEnhancedBlockSuppressionAfterEmergencyContact()368 public void testEnhancedBlockSuppressionAfterEmergencyContact() { 369 String phoneNumber = "5004541111"; 370 371 int blockSuppressionSeconds = 1000; 372 when(mMockContext.mCarrierConfigManager.getConfig()) 373 .thenReturn(getBundleWithInt(blockSuppressionSeconds)); 374 375 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, true); 376 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, true); 377 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, true); 378 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, true); 379 380 // After emergency contact blocks should be suppressed. 381 long timestampMillisBeforeEmergencyContact = System.currentTimeMillis(); 382 SystemContract.notifyEmergencyContact(mMockContext); 383 384 assertShouldSystemBlock(false, phoneNumber, 385 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); 386 assertShouldSystemBlock(false, phoneNumber, 387 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); 388 assertShouldSystemBlock(false, phoneNumber, 389 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); 390 assertShouldSystemBlock(false, phoneNumber, 391 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); 392 393 SystemContract.BlockSuppressionStatus status = 394 SystemContract.getBlockSuppressionStatus(mMockContext); 395 assertTrue(status.isSuppressed); 396 assertValidBlockSuppressionExpiration(timestampMillisBeforeEmergencyContact, 397 blockSuppressionSeconds, status.untilTimestampMillis); 398 assertEquals(1, mMockContext.mIntentsBroadcasted.size()); 399 assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, 400 mMockContext.mIntentsBroadcasted.get(0)); 401 mMockContext.mIntentsBroadcasted.clear(); 402 403 // Ending block suppression should work. 404 SystemContract.endBlockSuppression(mMockContext); 405 assertShouldSystemBlock(true, phoneNumber, 406 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); 407 assertShouldSystemBlock(true, phoneNumber, 408 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); 409 assertShouldSystemBlock(true, phoneNumber, 410 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); 411 assertShouldSystemBlock(true, phoneNumber, 412 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); 413 414 verifyBlocksNotSuppressed(); 415 assertEquals(1, mMockContext.mIntentsBroadcasted.size()); 416 assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, 417 mMockContext.mIntentsBroadcasted.get(0)); 418 } 419 testRegularAppCannotAccessApis()420 public void testRegularAppCannotAccessApis() { 421 doReturn(PackageManager.PERMISSION_DENIED) 422 .when(mMockContext).checkCallingPermission(anyString()); 423 424 try { 425 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 426 fail("SecurityException expected"); 427 } catch (SecurityException expected) { 428 } 429 430 try { 431 mResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 432 fail("SecurityException expected"); 433 } catch (SecurityException expected) { 434 } 435 436 try { 437 mResolver.delete(BlockedNumbers.CONTENT_URI, null, null); 438 fail("SecurityException expected"); 439 } catch (SecurityException expected) { 440 } 441 442 try { 443 BlockedNumberContract.isBlocked(mMockContext, "123"); 444 fail("SecurityException expected"); 445 } catch (SecurityException expected) { 446 } 447 448 try { 449 BlockedNumberContract.unblock(mMockContext, "123"); 450 fail("SecurityException expected"); 451 } catch (SecurityException expected) { 452 } 453 454 try { 455 SystemContract.notifyEmergencyContact(mMockContext); 456 fail("SecurityException expected"); 457 } catch (SecurityException expected) { 458 } 459 460 try { 461 SystemContract.endBlockSuppression(mMockContext); 462 fail("SecurityException expected"); 463 } catch (SecurityException expected) { 464 } 465 466 try { 467 SystemContract.shouldSystemBlockNumber(mMockContext, "123", null); 468 fail("SecurityException expected"); 469 } catch (SecurityException expected) { 470 } 471 472 try { 473 SystemContract.getBlockSuppressionStatus(mMockContext); 474 fail("SecurityException expected"); 475 } catch (SecurityException expected) { 476 } 477 } 478 testCarrierAppCanAccessApis()479 public void testCarrierAppCanAccessApis() { 480 doReturn(PackageManager.PERMISSION_DENIED) 481 .when(mMockContext).checkCallingPermission(anyString()); 482 when(mMockContext.mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(anyString())) 483 .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS); 484 485 mResolver.insert( 486 BlockedNumbers.CONTENT_URI, cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 487 assertIsBlocked(true, "123"); 488 489 490 // Dialer check is executed twice: once for insert, and once for isBlocked. 491 verify(mMockContext.mTelephonyManager, times(2)) 492 .checkCarrierPrivilegesForPackageAnyPhone(anyString()); 493 } 494 testSelfCanAccessApis()495 public void testSelfCanAccessApis() { 496 BlockedNumberProvider.ALLOW_SELF_CALL = true; 497 doReturn(PackageManager.PERMISSION_DENIED) 498 .when(mMockContext).checkCallingPermission(anyString()); 499 500 mResolver.insert( 501 BlockedNumbers.CONTENT_URI, cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 502 assertIsBlocked(true, "123"); 503 } 504 testDefaultDialerCanAccessApis()505 public void testDefaultDialerCanAccessApis() { 506 doReturn(PackageManager.PERMISSION_DENIED) 507 .when(mMockContext).checkCallingPermission(anyString()); 508 when(mMockContext.mTelecomManager.getDefaultDialerPackage()) 509 .thenReturn(getContext().getPackageName()); 510 511 mResolver.insert( 512 BlockedNumbers.CONTENT_URI, cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 513 assertIsBlocked(true, "123"); 514 515 // Dialer check is executed twice: once for insert, and once for isBlocked. 516 verify(mMockContext.mTelecomManager, times(2)).getDefaultDialerPackage(); 517 } 518 testPrivilegedAppCannotUseSystemApis()519 public void testPrivilegedAppCannotUseSystemApis() { 520 reset(mMockContext.mAppOpsManager); 521 doReturn(PackageManager.PERMISSION_DENIED) 522 .when(mMockContext).checkCallingPermission(anyString()); 523 524 // Pretend to be the Default SMS app. 525 when(mMockContext.mAppOpsManager.noteOp( 526 eq(AppOpsManager.OP_WRITE_SMS), anyInt(), anyString())) 527 .thenReturn(AppOpsManager.MODE_ALLOWED); 528 529 // Public APIs should work. 530 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 531 assertIsBlocked(true, "123"); 532 533 try { 534 SystemContract.notifyEmergencyContact(mMockContext); 535 fail("SecurityException expected"); 536 } catch (SecurityException expected) { 537 } 538 539 try { 540 SystemContract.endBlockSuppression(mMockContext); 541 fail("SecurityException expected"); 542 } catch (SecurityException expected) { 543 } 544 545 try { 546 SystemContract.shouldSystemBlockNumber(mMockContext, "123", null); 547 fail("SecurityException expected"); 548 } catch (SecurityException expected) { 549 } 550 551 try { 552 SystemContract.getBlockSuppressionStatus(mMockContext); 553 fail("SecurityException expected"); 554 } catch (SecurityException expected) { 555 } 556 } 557 testIsBlocked()558 public void testIsBlocked() { 559 assertTrue(BlockedNumberContract.canCurrentUserBlockNumbers(mMockContext)); 560 561 // Prepare test data 562 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 563 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "+1.2-3")); 564 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "+1-500-454-1111")); 565 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1-500-454-2222")); 566 567 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "045-111-2222", 568 BlockedNumbers.COLUMN_E164_NUMBER, "+81451112222")); 569 570 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "abc.def@gmail.com")); 571 572 // Check 573 assertIsBlocked(false, ""); 574 assertIsBlocked(false, null); 575 assertIsBlocked(true, "123"); 576 assertIsBlocked(false, "1234"); 577 assertIsBlocked(true, "+81451112222"); 578 assertIsBlocked(true, "+81 45 111 2222"); 579 assertIsBlocked(true, "045-111-2222"); 580 assertIsBlocked(false, "045 111 2222"); 581 582 assertIsBlocked(true, "500-454 1111"); 583 assertIsBlocked(true, "500-454 2222"); 584 assertIsBlocked(true, "+1 500-454 1111"); 585 assertIsBlocked(true, "1 500-454 1111"); 586 587 assertIsBlocked(true, "abc.def@gmail.com"); 588 assertIsBlocked(false, "abc.def@gmail.co"); 589 assertIsBlocked(false, "bc.def@gmail.com"); 590 assertIsBlocked(false, "abcdef@gmail.com"); 591 } 592 testUnblock()593 public void testUnblock() { 594 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "+1-500-454-1111")); 595 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1500-454-1111")); 596 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "abc.def@gmail.com")); 597 598 // Unblocking non-existent number is a no-op. 599 assertEquals(0, BlockedNumberContract.unblock(mMockContext, "12345")); 600 601 // Both rows which map to the same E164 number are deleted. 602 assertEquals(2, BlockedNumberContract.unblock(mMockContext, "5004541111")); 603 assertIsBlocked(false, "1-500-454-1111"); 604 605 assertEquals(1, BlockedNumberContract.unblock(mMockContext, "abc.def@gmail.com")); 606 assertIsBlocked(false, "abc.def@gmail.com"); 607 } 608 testEmergencyNumbersAreNotBlockedBySystem()609 public void testEmergencyNumbersAreNotBlockedBySystem() { 610 String emergencyNumber = getEmergencyNumberFromSystemPropertiesOrDefault(); 611 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, emergencyNumber)); 612 613 assertIsBlocked(true, emergencyNumber); 614 assertEquals(BlockedNumberContract.STATUS_NOT_BLOCKED, 615 SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, null)); 616 617 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, true); 618 assertEquals(BlockedNumberContract.STATUS_NOT_BLOCKED, 619 SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 620 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false))); 621 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, true); 622 assertEquals(BlockedNumberContract.STATUS_NOT_BLOCKED, 623 SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 624 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false))); 625 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, true); 626 assertEquals(BlockedNumberContract.STATUS_NOT_BLOCKED, 627 SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 628 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false))); 629 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, true); 630 assertEquals(BlockedNumberContract.STATUS_NOT_BLOCKED, 631 SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 632 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false))); 633 } 634 testPrivilegedAppAccessingApisAsSecondaryUser()635 public void testPrivilegedAppAccessingApisAsSecondaryUser() { 636 when(mMockContext.mUserManager.isPrimaryUser()).thenReturn(false); 637 638 assertFalse(BlockedNumberContract.canCurrentUserBlockNumbers(mMockContext)); 639 640 try { 641 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 642 fail("SecurityException expected"); 643 } catch (SecurityException expected) { 644 assertTrue(expected.getMessage().contains("current user")); 645 } 646 647 try { 648 mResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 649 fail("SecurityException expected"); 650 } catch (SecurityException expected) { 651 } 652 653 try { 654 mResolver.delete(BlockedNumbers.CONTENT_URI, null, null); 655 fail("SecurityException expected"); 656 } catch (SecurityException expected) { 657 } 658 659 try { 660 BlockedNumberContract.isBlocked(mMockContext, "123"); 661 fail("SecurityException expected"); 662 } catch (SecurityException expected) { 663 } 664 665 try { 666 BlockedNumberContract.unblock(mMockContext, "123"); 667 fail("SecurityException expected"); 668 } catch (SecurityException expected) { 669 } 670 } 671 testRegularAppAccessingApisAsSecondaryUser()672 public void testRegularAppAccessingApisAsSecondaryUser() { 673 when(mMockContext.mUserManager.isPrimaryUser()).thenReturn(false); 674 doReturn(PackageManager.PERMISSION_DENIED) 675 .when(mMockContext).checkCallingPermission(anyString()); 676 677 assertFalse(BlockedNumberContract.canCurrentUserBlockNumbers(mMockContext)); 678 679 try { 680 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 681 fail("SecurityException expected"); 682 } catch (SecurityException expected) { 683 } 684 685 try { 686 mResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 687 fail("SecurityException expected"); 688 } catch (SecurityException expected) { 689 } 690 691 try { 692 mResolver.delete(BlockedNumbers.CONTENT_URI, null, null); 693 fail("SecurityException expected"); 694 } catch (SecurityException expected) { 695 } 696 697 try { 698 BlockedNumberContract.isBlocked(mMockContext, "123"); 699 fail("SecurityException expected"); 700 } catch (SecurityException expected) { 701 } 702 703 try { 704 BlockedNumberContract.unblock(mMockContext, "123"); 705 fail("SecurityException expected"); 706 } catch (SecurityException expected) { 707 } 708 } 709 assertIsBlocked(boolean expected, String phoneNumber)710 private void assertIsBlocked(boolean expected, String phoneNumber) { 711 assertEquals(expected, BlockedNumberContract.isBlocked(mMockContext, phoneNumber)); 712 } 713 assertShouldSystemBlock(boolean expected, String phoneNumber, Bundle extras)714 private void assertShouldSystemBlock(boolean expected, String phoneNumber, Bundle extras) { 715 assertEquals(expected, 716 SystemContract.shouldSystemBlockNumber(mMockContext, phoneNumber, extras) 717 != BlockedNumberContract.STATUS_NOT_BLOCKED); 718 } 719 setEnhancedBlockSetting(String key, boolean value)720 private void setEnhancedBlockSetting(String key, boolean value) { 721 SystemContract.setEnhancedBlockSetting(mMockContext, key, value); 722 } 723 createBundleForEnhancedBlocking(int presentation, boolean contactExist)724 private Bundle createBundleForEnhancedBlocking(int presentation, boolean contactExist) { 725 Bundle extras = new Bundle(); 726 extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, presentation); 727 extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST, contactExist); 728 return extras; 729 } 730 getBundleWithInt(int value)731 private PersistableBundle getBundleWithInt(int value) { 732 PersistableBundle bundle = new PersistableBundle(); 733 bundle.putInt( 734 CarrierConfigManager.KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, value); 735 return bundle; 736 } 737 verifyBlocksNotSuppressed()738 private void verifyBlocksNotSuppressed() { 739 SystemContract.BlockSuppressionStatus status = 740 SystemContract.getBlockSuppressionStatus(mMockContext); 741 assertFalse(status.isSuppressed); 742 assertEquals(0, status.untilTimestampMillis); 743 } 744 assertValidBlockSuppressionExpiration(long timestampMillisBeforeEmergencyContact, int blockSuppressionSeconds, long actualExpirationMillis)745 private void assertValidBlockSuppressionExpiration(long timestampMillisBeforeEmergencyContact, 746 int blockSuppressionSeconds, 747 long actualExpirationMillis) { 748 assertTrue(actualExpirationMillis 749 >= timestampMillisBeforeEmergencyContact + blockSuppressionSeconds * 1000); 750 assertTrue(actualExpirationMillis < timestampMillisBeforeEmergencyContact + 751 2 * blockSuppressionSeconds * 1000); 752 } 753 754 private void assertContents(int rowId, String originalNumber, String e164Number) { 755 Uri uri = ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, rowId); 756 try (Cursor c = mResolver.query(uri, null, null, null, null)) { 757 assertEquals(1, c.getCount()); 758 c.moveToNext(); 759 assertEquals(3, c.getColumnCount()); 760 assertEquals(rowId, c.getInt(c.getColumnIndex(BlockedNumbers.COLUMN_ID))); 761 assertEquals(originalNumber, 762 c.getString(c.getColumnIndex(BlockedNumbers.COLUMN_ORIGINAL_NUMBER))); 763 assertEquals(e164Number, 764 c.getString(c.getColumnIndex(BlockedNumbers.COLUMN_E164_NUMBER))); 765 } 766 } 767 768 private String getEmergencyNumberFromSystemPropertiesOrDefault() { 769 String systemEmergencyNumbers = SystemProperties.get("ril.ecclist"); 770 if (systemEmergencyNumbers == null) { 771 return "911"; 772 } else { 773 return systemEmergencyNumbers.split(",")[0]; 774 } 775 } 776 } 777