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.checkCarrierPrivilegesForPackage(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 .checkCarrierPrivilegesForPackage(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 assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, null)); 615 616 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, true); 617 assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 618 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false))); 619 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, true); 620 assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 621 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false))); 622 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, true); 623 assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 624 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false))); 625 setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, true); 626 assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, 627 createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false))); 628 } 629 testPrivilegedAppAccessingApisAsSecondaryUser()630 public void testPrivilegedAppAccessingApisAsSecondaryUser() { 631 when(mMockContext.mUserManager.isPrimaryUser()).thenReturn(false); 632 633 assertFalse(BlockedNumberContract.canCurrentUserBlockNumbers(mMockContext)); 634 635 try { 636 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 637 fail("SecurityException expected"); 638 } catch (SecurityException expected) { 639 assertTrue(expected.getMessage().contains("current user")); 640 } 641 642 try { 643 mResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 644 fail("SecurityException expected"); 645 } catch (SecurityException expected) { 646 } 647 648 try { 649 mResolver.delete(BlockedNumbers.CONTENT_URI, null, null); 650 fail("SecurityException expected"); 651 } catch (SecurityException expected) { 652 } 653 654 try { 655 BlockedNumberContract.isBlocked(mMockContext, "123"); 656 fail("SecurityException expected"); 657 } catch (SecurityException expected) { 658 } 659 660 try { 661 BlockedNumberContract.unblock(mMockContext, "123"); 662 fail("SecurityException expected"); 663 } catch (SecurityException expected) { 664 } 665 } 666 testRegularAppAccessingApisAsSecondaryUser()667 public void testRegularAppAccessingApisAsSecondaryUser() { 668 when(mMockContext.mUserManager.isPrimaryUser()).thenReturn(false); 669 doReturn(PackageManager.PERMISSION_DENIED) 670 .when(mMockContext).checkCallingPermission(anyString()); 671 672 assertFalse(BlockedNumberContract.canCurrentUserBlockNumbers(mMockContext)); 673 674 try { 675 insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "123")); 676 fail("SecurityException expected"); 677 } catch (SecurityException expected) { 678 } 679 680 try { 681 mResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null); 682 fail("SecurityException expected"); 683 } catch (SecurityException expected) { 684 } 685 686 try { 687 mResolver.delete(BlockedNumbers.CONTENT_URI, null, null); 688 fail("SecurityException expected"); 689 } catch (SecurityException expected) { 690 } 691 692 try { 693 BlockedNumberContract.isBlocked(mMockContext, "123"); 694 fail("SecurityException expected"); 695 } catch (SecurityException expected) { 696 } 697 698 try { 699 BlockedNumberContract.unblock(mMockContext, "123"); 700 fail("SecurityException expected"); 701 } catch (SecurityException expected) { 702 } 703 } 704 assertIsBlocked(boolean expected, String phoneNumber)705 private void assertIsBlocked(boolean expected, String phoneNumber) { 706 assertEquals(expected, BlockedNumberContract.isBlocked(mMockContext, phoneNumber)); 707 } 708 assertShouldSystemBlock(boolean expected, String phoneNumber, Bundle extras)709 private void assertShouldSystemBlock(boolean expected, String phoneNumber, Bundle extras) { 710 assertEquals(expected, SystemContract.shouldSystemBlockNumber(mMockContext, phoneNumber, 711 extras)); 712 } 713 setEnhancedBlockSetting(String key, boolean value)714 private void setEnhancedBlockSetting(String key, boolean value) { 715 SystemContract.setEnhancedBlockSetting(mMockContext, key, value); 716 } 717 createBundleForEnhancedBlocking(int presentation, boolean contactExist)718 private Bundle createBundleForEnhancedBlocking(int presentation, boolean contactExist) { 719 Bundle extras = new Bundle(); 720 extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, presentation); 721 extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST, contactExist); 722 return extras; 723 } 724 getBundleWithInt(int value)725 private PersistableBundle getBundleWithInt(int value) { 726 PersistableBundle bundle = new PersistableBundle(); 727 bundle.putInt( 728 CarrierConfigManager.KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, value); 729 return bundle; 730 } 731 verifyBlocksNotSuppressed()732 private void verifyBlocksNotSuppressed() { 733 SystemContract.BlockSuppressionStatus status = 734 SystemContract.getBlockSuppressionStatus(mMockContext); 735 assertFalse(status.isSuppressed); 736 assertEquals(0, status.untilTimestampMillis); 737 } 738 assertValidBlockSuppressionExpiration(long timestampMillisBeforeEmergencyContact, int blockSuppressionSeconds, long actualExpirationMillis)739 private void assertValidBlockSuppressionExpiration(long timestampMillisBeforeEmergencyContact, 740 int blockSuppressionSeconds, 741 long actualExpirationMillis) { 742 assertTrue(actualExpirationMillis 743 >= timestampMillisBeforeEmergencyContact + blockSuppressionSeconds * 1000); 744 assertTrue(actualExpirationMillis < timestampMillisBeforeEmergencyContact + 745 2 * blockSuppressionSeconds * 1000); 746 } 747 748 private void assertContents(int rowId, String originalNumber, String e164Number) { 749 Uri uri = ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, rowId); 750 try (Cursor c = mResolver.query(uri, null, null, null, null)) { 751 assertEquals(1, c.getCount()); 752 c.moveToNext(); 753 assertEquals(3, c.getColumnCount()); 754 assertEquals(rowId, c.getInt(c.getColumnIndex(BlockedNumbers.COLUMN_ID))); 755 assertEquals(originalNumber, 756 c.getString(c.getColumnIndex(BlockedNumbers.COLUMN_ORIGINAL_NUMBER))); 757 assertEquals(e164Number, 758 c.getString(c.getColumnIndex(BlockedNumbers.COLUMN_E164_NUMBER))); 759 } 760 } 761 762 private String getEmergencyNumberFromSystemPropertiesOrDefault() { 763 String systemEmergencyNumbers = SystemProperties.get("ril.ecclist"); 764 if (systemEmergencyNumbers == null) { 765 return "911"; 766 } else { 767 return systemEmergencyNumbers.split(",")[0]; 768 } 769 } 770 } 771