diff options
author | Tyler Gunn <tgunn@google.com> | 2018-03-09 02:33:43 +0000 |
---|---|---|
committer | Tyler Gunn <tgunn@google.com> | 2018-03-09 20:47:45 +0000 |
commit | fee5c9f28140efca9a91249e7e46744af7644f47 (patch) | |
tree | c2ce2e41a3b8c62f4c787088f9771c65f41f682d | |
parent | 8f68ef131d2fd2d87caac0fcbe67df7abd166c9d (diff) | |
download | BlockedNumberProvider-fee5c9f28140efca9a91249e7e46744af7644f47.tar.gz |
Support enhanced call blocking function
- Add new method to get/set the call blocking enabled status.
- Improve the method of checking whether a number is block number
by supporting extras.
Bug: 28189985
Test: Manual
Merged-In: Idd4d97e9a244c6ecf7b398d597eb20fa4e369ccc
Change-Id: Idd4d97e9a244c6ecf7b398d597eb20fa4e369ccc
(cherry picked from commit cbc648ca501af600c43b8c86e5684997d4b728b0)
-rw-r--r-- | src/com/android/providers/blockednumber/BlockedNumberProvider.java | 123 | ||||
-rw-r--r-- | tests/src/com/android/providers/blockednumber/BlockedNumberProviderTest.java | 137 |
2 files changed, 240 insertions, 20 deletions
diff --git a/src/com/android/providers/blockednumber/BlockedNumberProvider.java b/src/com/android/providers/blockednumber/BlockedNumberProvider.java index 6d96188..44a5f84 100644 --- a/src/com/android/providers/blockednumber/BlockedNumberProvider.java +++ b/src/com/android/providers/blockednumber/BlockedNumberProvider.java @@ -35,6 +35,7 @@ import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.CancellationSignal; +import android.os.PersistableBundle; import android.os.Process; import android.os.UserManager; import android.provider.BlockedNumberContract; @@ -72,6 +73,7 @@ public class BlockedNumberProvider extends ContentProvider { private static final String BLOCK_SUPPRESSION_EXPIRY_TIME_PREF = "block_suppression_expiry_time_pref"; private static final int MAX_BLOCKING_DISABLED_DURATION_SECONDS = 7 * 24 * 3600; // 1 week + private static final long BLOCKING_DISABLED_FOREVER = -1; // Normally, we allow calls from self, *except* in unit tests, where we clear this flag // to emulate calls from other apps. @VisibleForTesting @@ -339,8 +341,30 @@ public class BlockedNumberProvider extends ContentProvider { break; case SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER: enforceSystemReadPermissionAndPrimaryUser(); - res.putBoolean( - BlockedNumberContract.RES_NUMBER_IS_BLOCKED, shouldSystemBlockNumber(arg)); + res.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, + shouldSystemBlockNumber(arg, extras)); + break; + case SystemContract.METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION: + enforceSystemReadPermissionAndPrimaryUser(); + res.putBoolean(BlockedNumberContract.RES_SHOW_EMERGENCY_CALL_NOTIFICATION, + shouldShowEmergencyCallNotification()); + break; + case SystemContract.METHOD_GET_ENHANCED_BLOCK_SETTING: + enforceSystemReadPermissionAndPrimaryUser(); + if (extras != null) { + String key = extras.getString(BlockedNumberContract.EXTRA_ENHANCED_SETTING_KEY); + boolean value = getEnhancedBlockSetting(key); + res.putBoolean(BlockedNumberContract.RES_ENHANCED_SETTING_IS_ENABLED, value); + } + break; + case SystemContract.METHOD_SET_ENHANCED_BLOCK_SETTING: + enforceSystemWritePermissionAndPrimaryUser(); + if (extras != null) { + String key = extras.getString(BlockedNumberContract.EXTRA_ENHANCED_SETTING_KEY); + boolean value = extras.getBoolean( + BlockedNumberContract.EXTRA_ENHANCED_SETTING_VALUE, false); + setEnhancedBlockSetting(key, value); + } break; default: enforceReadPermissionAndPrimaryUser(); @@ -424,8 +448,11 @@ public class BlockedNumberProvider extends ContentProvider { } private void notifyEmergencyContact() { - writeBlockSuppressionExpiryTimePref(System.currentTimeMillis() + - getBlockSuppressSecondsFromCarrierConfig() * 1000); + long sec = getBlockSuppressSecondsFromCarrierConfig(); + long millisToWrite = sec < 0 + ? BLOCKING_DISABLED_FOREVER : System.currentTimeMillis() + (sec * 1000); + writeBlockSuppressionExpiryTimePref(millisToWrite); + writeEmergencyCallNotificationPref(true); notifyBlockSuppressionStateChange(); } @@ -433,6 +460,7 @@ public class BlockedNumberProvider extends ContentProvider { // Nothing to do if blocks are not being suppressed. if (getBlockSuppressionStatus().isSuppressed) { writeBlockSuppressionExpiryTimePref(0); + writeEmergencyCallNotificationPref(false); notifyBlockSuppressionStateChange(); } } @@ -440,18 +468,94 @@ public class BlockedNumberProvider extends ContentProvider { private SystemContract.BlockSuppressionStatus getBlockSuppressionStatus() { SharedPreferences pref = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); long blockSuppressionExpiryTimeMillis = pref.getLong(BLOCK_SUPPRESSION_EXPIRY_TIME_PREF, 0); - return new SystemContract.BlockSuppressionStatus(System.currentTimeMillis() < - blockSuppressionExpiryTimeMillis, blockSuppressionExpiryTimeMillis); + boolean isSuppressed = blockSuppressionExpiryTimeMillis == BLOCKING_DISABLED_FOREVER + || System.currentTimeMillis() < blockSuppressionExpiryTimeMillis; + return new SystemContract.BlockSuppressionStatus(isSuppressed, + blockSuppressionExpiryTimeMillis); } - private boolean shouldSystemBlockNumber(String phoneNumber) { + private boolean shouldSystemBlockNumber(String phoneNumber, Bundle extras) { if (getBlockSuppressionStatus().isSuppressed) { return false; } if (isEmergencyNumber(phoneNumber)) { return false; } - return isBlocked(phoneNumber); + + boolean isBlocked = false; + if (extras != null && !extras.isEmpty()) { + // check enhanced blocking setting + boolean contactExist = extras.getBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST); + int presentation = extras.getInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION); + switch (presentation) { + case TelecomManager.PRESENTATION_ALLOWED: + isBlocked = getEnhancedBlockSetting( + SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED) + && !contactExist; + break; + case TelecomManager.PRESENTATION_RESTRICTED: + isBlocked = getEnhancedBlockSetting( + SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE); + break; + case TelecomManager.PRESENTATION_PAYPHONE: + isBlocked = getEnhancedBlockSetting( + SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE); + break; + case TelecomManager.PRESENTATION_UNKNOWN: + isBlocked = getEnhancedBlockSetting( + SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN); + break; + default: + break; + } + } + return isBlocked || isBlocked(phoneNumber); + } + + private boolean shouldShowEmergencyCallNotification() { + return isEnhancedCallBlockingEnabledByPlatform() + && isAnyEnhancedBlockingSettingEnabled() + && getBlockSuppressionStatus().isSuppressed + && getEnhancedBlockSetting( + SystemContract.ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION); + } + + private boolean isEnhancedCallBlockingEnabledByPlatform() { + CarrierConfigManager configManager = (CarrierConfigManager) getContext().getSystemService( + Context.CARRIER_CONFIG_SERVICE); + PersistableBundle carrierConfig = configManager.getConfig(); + if (carrierConfig == null) { + carrierConfig = configManager.getDefaultConfig(); + } + return carrierConfig.getBoolean( + CarrierConfigManager.KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL); + } + + private boolean isAnyEnhancedBlockingSettingEnabled() { + return getEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED) + || getEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE) + || getEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE) + || getEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN); + } + + private boolean getEnhancedBlockSetting(String key) { + SharedPreferences pref = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); + return pref.getBoolean(key, false); + } + + private void setEnhancedBlockSetting(String key, boolean value) { + SharedPreferences pref = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = pref.edit(); + editor.putBoolean(key, value); + editor.apply(); + } + + private void writeEmergencyCallNotificationPref(boolean show) { + if (!isEnhancedCallBlockingEnabledByPlatform()) { + return; + } + setEnhancedBlockSetting( + SystemContract.ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION, show); } private void writeBlockSuppressionExpiryTimePref(long expiryTimeMillis) { @@ -466,8 +570,7 @@ public class BlockedNumberProvider extends ContentProvider { getContext().getSystemService(CarrierConfigManager.class); int carrierConfigValue = carrierConfigManager.getConfig().getInt (CarrierConfigManager.KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT); - boolean isValidValue = carrierConfigValue >=0 && carrierConfigValue <= - MAX_BLOCKING_DISABLED_DURATION_SECONDS; + boolean isValidValue = carrierConfigValue <= MAX_BLOCKING_DISABLED_DURATION_SECONDS; return isValidValue ? carrierConfigValue : CarrierConfigManager.getDefaultConfig().getInt( CarrierConfigManager.KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT); } diff --git a/tests/src/com/android/providers/blockednumber/BlockedNumberProviderTest.java b/tests/src/com/android/providers/blockednumber/BlockedNumberProviderTest.java index 6c703b8..91d2430 100644 --- a/tests/src/com/android/providers/blockednumber/BlockedNumberProviderTest.java +++ b/tests/src/com/android/providers/blockednumber/BlockedNumberProviderTest.java @@ -35,11 +35,13 @@ import android.database.Cursor; import android.database.sqlite.SQLiteException; import android.location.Country; import android.net.Uri; +import android.os.Bundle; import android.os.PersistableBundle; import android.os.SystemProperties; import android.provider.BlockedNumberContract; import android.provider.BlockedNumberContract.BlockedNumbers; import android.provider.BlockedNumberContract.SystemContract; +import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; import android.test.AndroidTestCase; @@ -267,14 +269,14 @@ public class BlockedNumberProviderTest extends AndroidTestCase { // No emergency contact: Blocks should not be suppressed. assertIsBlocked(true, phoneNumber); - assertShouldSystemBlock(true, phoneNumber); + assertShouldSystemBlock(true, phoneNumber, null); verifyBlocksNotSuppressed(); assertTrue(mMockContext.mIntentsBroadcasted.isEmpty()); // No emergency contact yet: Ending block suppression should be a no-op. SystemContract.endBlockSuppression(mMockContext); assertIsBlocked(true, phoneNumber); - assertShouldSystemBlock(true, phoneNumber); + assertShouldSystemBlock(true, phoneNumber, null); verifyBlocksNotSuppressed(); assertTrue(mMockContext.mIntentsBroadcasted.isEmpty()); @@ -282,7 +284,7 @@ public class BlockedNumberProviderTest extends AndroidTestCase { long timestampMillisBeforeEmergencyContact = System.currentTimeMillis(); SystemContract.notifyEmergencyContact(mMockContext); assertIsBlocked(true, phoneNumber); - assertShouldSystemBlock(false, phoneNumber); + assertShouldSystemBlock(false, phoneNumber, null); SystemContract.BlockSuppressionStatus status = SystemContract.getBlockSuppressionStatus(mMockContext); assertTrue(status.isSuppressed); @@ -296,7 +298,7 @@ public class BlockedNumberProviderTest extends AndroidTestCase { // Ending block suppression should work. SystemContract.endBlockSuppression(mMockContext); assertIsBlocked(true, phoneNumber); - assertShouldSystemBlock(true, phoneNumber); + assertShouldSystemBlock(true, phoneNumber, null); verifyBlocksNotSuppressed(); assertEquals(1, mMockContext.mIntentsBroadcasted.size()); assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, @@ -314,7 +316,7 @@ public class BlockedNumberProviderTest extends AndroidTestCase { long timestampMillisBeforeEmergencyContact = System.currentTimeMillis(); SystemContract.notifyEmergencyContact(mMockContext); assertIsBlocked(true, phoneNumber); - assertShouldSystemBlock(false, phoneNumber); + assertShouldSystemBlock(false, phoneNumber, null); SystemContract.BlockSuppressionStatus status = SystemContract.getBlockSuppressionStatus(mMockContext); assertTrue(status.isSuppressed); @@ -325,6 +327,96 @@ public class BlockedNumberProviderTest extends AndroidTestCase { mMockContext.mIntentsBroadcasted.get(0)); } + public void testEnhancedBlock() { + String phoneNumber = "5004541111"; + + // Check whether block numbers not in contacts setting works well + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, true); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, true)); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, false); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); + + // Check whether block private number calls setting works well + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, true); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, false); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); + + // Check whether block payphone calls setting works well + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, true); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, false); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); + + // Check whether block unknown calls setting works well + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, true); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, false); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); + } + + public void testEnhancedBlockSuppressionAfterEmergencyContact() { + String phoneNumber = "5004541111"; + + int blockSuppressionSeconds = 1000; + when(mMockContext.mCarrierConfigManager.getConfig()) + .thenReturn(getBundleWithInt(blockSuppressionSeconds)); + + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, true); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, true); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, true); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, true); + + // After emergency contact blocks should be suppressed. + long timestampMillisBeforeEmergencyContact = System.currentTimeMillis(); + SystemContract.notifyEmergencyContact(mMockContext); + + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); + assertShouldSystemBlock(false, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); + + SystemContract.BlockSuppressionStatus status = + SystemContract.getBlockSuppressionStatus(mMockContext); + assertTrue(status.isSuppressed); + assertValidBlockSuppressionExpiration(timestampMillisBeforeEmergencyContact, + blockSuppressionSeconds, status.untilTimestampMillis); + assertEquals(1, mMockContext.mIntentsBroadcasted.size()); + assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, + mMockContext.mIntentsBroadcasted.get(0)); + mMockContext.mIntentsBroadcasted.clear(); + + // Ending block suppression should work. + SystemContract.endBlockSuppression(mMockContext); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false)); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false)); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false)); + assertShouldSystemBlock(true, phoneNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false)); + + verifyBlocksNotSuppressed(); + assertEquals(1, mMockContext.mIntentsBroadcasted.size()); + assertEquals(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED, + mMockContext.mIntentsBroadcasted.get(0)); + } + public void testRegularAppCannotAccessApis() { doReturn(PackageManager.PERMISSION_DENIED) .when(mMockContext).checkCallingPermission(anyString()); @@ -372,7 +464,7 @@ public class BlockedNumberProviderTest extends AndroidTestCase { } try { - SystemContract.shouldSystemBlockNumber(mMockContext, "123"); + SystemContract.shouldSystemBlockNumber(mMockContext, "123", null); fail("SecurityException expected"); } catch (SecurityException expected) { } @@ -451,7 +543,7 @@ public class BlockedNumberProviderTest extends AndroidTestCase { } try { - SystemContract.shouldSystemBlockNumber(mMockContext, "123"); + SystemContract.shouldSystemBlockNumber(mMockContext, "123", null); fail("SecurityException expected"); } catch (SecurityException expected) { } @@ -519,7 +611,20 @@ public class BlockedNumberProviderTest extends AndroidTestCase { insert(cv(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, emergencyNumber)); assertIsBlocked(true, emergencyNumber); - assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber)); + assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, null)); + + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED, true); + assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_ALLOWED, false))); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE, true); + assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_RESTRICTED, false))); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE, true); + assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_PAYPHONE, false))); + setEnhancedBlockSetting(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN, true); + assertFalse(SystemContract.shouldSystemBlockNumber(mMockContext, emergencyNumber, + createBundleForEnhancedBlocking(TelecomManager.PRESENTATION_UNKNOWN, false))); } public void testPrivilegedAppAccessingApisAsSecondaryUser() { @@ -601,8 +706,20 @@ public class BlockedNumberProviderTest extends AndroidTestCase { assertEquals(expected, BlockedNumberContract.isBlocked(mMockContext, phoneNumber)); } - private void assertShouldSystemBlock(boolean expected, String phoneNumber) { - assertEquals(expected, SystemContract.shouldSystemBlockNumber(mMockContext, phoneNumber)); + private void assertShouldSystemBlock(boolean expected, String phoneNumber, Bundle extras) { + assertEquals(expected, SystemContract.shouldSystemBlockNumber(mMockContext, phoneNumber, + extras)); + } + + private void setEnhancedBlockSetting(String key, boolean value) { + SystemContract.setEnhancedBlockSetting(mMockContext, key, value); + } + + private Bundle createBundleForEnhancedBlocking(int presentation, boolean contactExist) { + Bundle extras = new Bundle(); + extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, presentation); + extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST, contactExist); + return extras; } private PersistableBundle getBundleWithInt(int value) { |