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