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