/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */
package android.provider;

import android.annotation.WorkerThread;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.telecom.Log;

The contract between the blockednumber provider and applications. Contains definitions for the supported URIs and columns.

Overview

The content provider exposes a table containing blocked numbers. The columns and URIs for accessing this table are defined by the BlockedNumbers class. Messages, and calls from blocked numbers are discarded by the platform. Notifications upon provider changes can be received using a ContentObserver.

The platform will not block messages, and calls from emergency numbers as defined by PhoneNumberUtils.isEmergencyNumber(String). If the user contacts emergency services, number blocking is disabled by the platform for a duration defined by CarrierConfigManager.KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT.

Permissions

Only the system, the default SMS application, and the default phone app (See TelecomManager.getDefaultDialerPackage()), and carrier apps (See CarrierService) can read, and write to the blockednumber provider. However, canCurrentUserBlockNumbers(Context) can be accessed by any application.

Data

Other than regular phone numbers, the blocked number provider can also store addresses (such as email) from which a user can receive messages, and calls. The blocked numbers are stored in the BlockedNumbers.COLUMN_ORIGINAL_NUMBER column. A normalized version of phone numbers (if normalization is possible) is stored in BlockedNumbers.COLUMN_E164_NUMBER column. The platform blocks calls, and messages from an address if it is present in in the BlockedNumbers.COLUMN_ORIGINAL_NUMBER column or if the E164 version of the address matches the BlockedNumbers.COLUMN_E164_NUMBER column.

Operations

Insert

BlockedNumbers.COLUMN_ORIGINAL_NUMBER is a required column that needs to be populated. Apps can optionally provide the BlockedNumbers.COLUMN_E164_NUMBER which is the phone number's E164 representation. The provider automatically populates this column if the app does not provide it. Note that this column is not populated if normalization fails or if the address is not a phone number (eg: email).

Attempting to insert an existing blocked number (same BlockedNumbers.COLUMN_ORIGINAL_NUMBER column) will result in replacing the existing blocked number.

Examples:

ContentValues values = new ContentValues();
values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
ContentValues values = new ContentValues();
values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
values.put(BlockedNumbers.COLUMN_E164_NUMBER, "+11234567890");
Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
ContentValues values = new ContentValues();
values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "12345@abdcde.com");
Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);

Update

Updates are not supported. Use Delete, and Insert instead.

Delete

Deletions can be performed as follows:

ContentValues values = new ContentValues();
values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
getContentResolver().delete(uri, null, null);
To check if a particular number is blocked, use the method isBlocked(Context, String).

Query

All blocked numbers can be enumerated as follows:

Cursor c = getContentResolver().query(BlockedNumbers.CONTENT_URI,
         new String[]{BlockedNumbers.COLUMN_ID, BlockedNumbers.COLUMN_ORIGINAL_NUMBER,
         BlockedNumbers.COLUMN_E164_NUMBER}, null, null, null);

Unblock

Use the method unblock(Context, String) to unblock numbers.

Multi-user

Apps must use the method canCurrentUserBlockNumbers(Context) before performing any operation on the blocked number provider. If canCurrentUserBlockNumbers(Context) returns false, all operations on the provider will fail with a SecurityException. The platform will block calls, and messages from numbers in the provider independent of the current user.

/** * <p> * The contract between the blockednumber provider and applications. Contains definitions for * the supported URIs and columns. * </p> * * <h3> Overview </h3> * <p> * The content provider exposes a table containing blocked numbers. The columns and URIs for * accessing this table are defined by the {@link BlockedNumbers} class. Messages, and calls from * blocked numbers are discarded by the platform. Notifications upon provider changes can be * received using a {@link android.database.ContentObserver}. * </p> * <p> * The platform will not block messages, and calls from emergency numbers as defined by * {@link android.telephony.PhoneNumberUtils#isEmergencyNumber(String)}. If the user contacts * emergency services, number blocking is disabled by the platform for a duration defined by * {@link android.telephony.CarrierConfigManager#KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT}. * </p> * * <h3> Permissions </h3> * <p> * Only the system, the default SMS application, and the default phone app * (See {@link android.telecom.TelecomManager#getDefaultDialerPackage()}), and carrier apps * (See {@link android.service.carrier.CarrierService}) can read, and write to the blockednumber * provider. However, {@link #canCurrentUserBlockNumbers(Context)} can be accessed by any * application. * </p> * * <h3> Data </h3> * <p> * Other than regular phone numbers, the blocked number provider can also store addresses (such * as email) from which a user can receive messages, and calls. The blocked numbers are stored * in the {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column. A normalized version of phone * numbers (if normalization is possible) is stored in {@link BlockedNumbers#COLUMN_E164_NUMBER} * column. The platform blocks calls, and messages from an address if it is present in in the * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column or if the E164 version of the address * matches the {@link BlockedNumbers#COLUMN_E164_NUMBER} column. * </p> * * <h3> Operations </h3> * <dl> * <dt><b>Insert</b></dt> * <dd> * <p> * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} is a required column that needs to be populated. * Apps can optionally provide the {@link BlockedNumbers#COLUMN_E164_NUMBER} which is the phone * number's E164 representation. The provider automatically populates this column if the app does * not provide it. Note that this column is not populated if normalization fails or if the address * is not a phone number (eg: email). * <p> * Attempting to insert an existing blocked number (same * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column) will result in replacing the existing * blocked number. * <p> * Examples: * <pre> * ContentValues values = new ContentValues(); * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890"); * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values); * </pre> * <pre> * ContentValues values = new ContentValues(); * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890"); * values.put(BlockedNumbers.COLUMN_E164_NUMBER, "+11234567890"); * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values); * </pre> * <pre> * ContentValues values = new ContentValues(); * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "12345@abdcde.com"); * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values); * </pre> * </p> * </dd> * <dt><b>Update</b></dt> * <dd> * <p> * Updates are not supported. Use Delete, and Insert instead. * </p> * </dd> * <dt><b>Delete</b></dt> * <dd> * <p> * Deletions can be performed as follows: * <pre> * ContentValues values = new ContentValues(); * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890"); * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values); * getContentResolver().delete(uri, null, null); * </pre> * To check if a particular number is blocked, use the method * {@link #isBlocked(Context, String)}. * </p> * </dd> * <dt><b>Query</b></dt> * <dd> * <p> * All blocked numbers can be enumerated as follows: * <pre> * Cursor c = getContentResolver().query(BlockedNumbers.CONTENT_URI, * new String[]{BlockedNumbers.COLUMN_ID, BlockedNumbers.COLUMN_ORIGINAL_NUMBER, * BlockedNumbers.COLUMN_E164_NUMBER}, null, null, null); * </pre> * </p> * </dd> * <dt><b>Unblock</b></dt> * <dd> * <p> * Use the method {@link #unblock(Context, String)} to unblock numbers. * </p> * </dd> * * <h3> Multi-user </h3> * <p> * Apps must use the method {@link #canCurrentUserBlockNumbers(Context)} before performing any * operation on the blocked number provider. If {@link #canCurrentUserBlockNumbers(Context)} returns * {@code false}, all operations on the provider will fail with a {@link SecurityException}. The * platform will block calls, and messages from numbers in the provider independent of the current * user. * </p> */
public class BlockedNumberContract { private BlockedNumberContract() { }
The authority for the blocked number provider
/** The authority for the blocked number provider */
public static final String AUTHORITY = "com.android.blockednumber";
A content:// style uri to the authority for the blocked number provider
/** A content:// style uri to the authority for the blocked number provider */
public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
Constants to interact with the blocked numbers list.
/** * Constants to interact with the blocked numbers list. */
public static class BlockedNumbers { private BlockedNumbers() { }
Content URI for the blocked numbers.

Supported operations

blocked

  • query
  • delete
  • insert

blocked/ID

  • query (selection is not supported)
  • delete (selection is not supported)
/** * Content URI for the blocked numbers. * <h3> Supported operations </h3> * <p> blocked * <ul> * <li> query * <li> delete * <li> insert * </ul> * <p> blocked/ID * <ul> * <li> query (selection is not supported) * <li> delete (selection is not supported) * </ul> */
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "blocked");
The MIME type of CONTENT_URI itself providing a directory of blocked phone numbers.
/** * The MIME type of {@link #CONTENT_URI} itself providing a directory of blocked phone * numbers. */
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
The MIME type of a blocked phone number under CONTENT_URI.
/** * The MIME type of a blocked phone number under {@link #CONTENT_URI}. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
Auto-generated ID field which monotonically increases.

TYPE: long

/** * Auto-generated ID field which monotonically increases. * <p>TYPE: long</p> */
public static final String COLUMN_ID = "_id";
Phone number to block.

Must be specified in insert.

TYPE: String

/** * Phone number to block. * <p>Must be specified in {@code insert}. * <p>TYPE: String</p> */
public static final String COLUMN_ORIGINAL_NUMBER = "original_number";
Phone number to block. The system generates it from COLUMN_ORIGINAL_NUMBER by removing all formatting characters.

Optional in insert. When not specified, the system tries to generate it assuming the current country. (Which will still be null if the number is not valid.)

TYPE: String

/** * Phone number to block. The system generates it from {@link #COLUMN_ORIGINAL_NUMBER} * by removing all formatting characters. * <p>Optional in {@code insert}. When not specified, the system tries to generate it * assuming the current country. (Which will still be null if the number is not valid.) * <p>TYPE: String</p> */
public static final String COLUMN_E164_NUMBER = "e164_number"; }
@hide
/** @hide */
public static final String METHOD_IS_BLOCKED = "is_blocked";
@hide
/** @hide */
public static final String METHOD_UNBLOCK= "unblock";
@hide
/** @hide */
public static final String RES_NUMBER_IS_BLOCKED = "blocked";
@hide
/** @hide */
public static final String RES_NUM_ROWS_DELETED = "num_deleted";
@hide
/** @hide */
public static final String METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS = "can_current_user_block_numbers";
@hide
/** @hide */
public static final String RES_CAN_BLOCK_NUMBERS = "can_block";
@hide
/** @hide */
public static final String RES_ENHANCED_SETTING_IS_ENABLED = "enhanced_setting_enabled";
@hide
/** @hide */
public static final String RES_SHOW_EMERGENCY_CALL_NOTIFICATION = "show_emergency_call_notification";
@hide
/** @hide */
public static final String EXTRA_ENHANCED_SETTING_KEY = "extra_enhanced_setting_key";
@hide
/** @hide */
public static final String EXTRA_ENHANCED_SETTING_VALUE = "extra_enhanced_setting_value";
@hide
/** @hide */
public static final String EXTRA_CONTACT_EXIST = "extra_contact_exist";
@hide
/** @hide */
public static final String EXTRA_CALL_PRESENTATION = "extra_call_presentation";
Returns whether a given number is in the blocked list.

This matches the phoneNumber against the BlockedNumbers.COLUMN_ORIGINAL_NUMBER column, and the E164 representation of the phoneNumber with the BlockedNumbers.COLUMN_E164_NUMBER column.

Note that if the canCurrentUserBlockNumbers is false for the user context context, this method will throw a SecurityException.

Returns:true if the phoneNumber is blocked.
/** * Returns whether a given number is in the blocked list. * * <p> This matches the {@code phoneNumber} against the * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column, and the E164 representation of the * {@code phoneNumber} with the {@link BlockedNumbers#COLUMN_E164_NUMBER} column. * * <p> Note that if the {@link #canCurrentUserBlockNumbers} is {@code false} for the user * context {@code context}, this method will throw a {@link SecurityException}. * * @return {@code true} if the {@code phoneNumber} is blocked. */
@WorkerThread public static boolean isBlocked(Context context, String phoneNumber) { try { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_IS_BLOCKED, phoneNumber, null); return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false); } catch (NullPointerException | IllegalArgumentException ex) { // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if // either of these happen. Log.w(null, "isBlocked: provider not ready."); return false; } }
Unblocks the phoneNumber if it is blocked.

This deletes all rows where the phoneNumber matches the BlockedNumbers.COLUMN_ORIGINAL_NUMBER column or the E164 representation of the phoneNumber matches the BlockedNumbers.COLUMN_E164_NUMBER column.

To delete rows based on exact match with specific columns such as BlockedNumbers.COLUMN_ID use ContentProvider.delete(Uri, String, String[]) with BlockedNumbers.CONTENT_URI URI.

Note that if the canCurrentUserBlockNumbers is false for the user context context, this method will throw a SecurityException.

Returns:the number of rows deleted in the blocked number provider as a result of unblock.
/** * Unblocks the {@code phoneNumber} if it is blocked. * * <p> This deletes all rows where the {@code phoneNumber} matches the * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column or the E164 representation of the * {@code phoneNumber} matches the {@link BlockedNumbers#COLUMN_E164_NUMBER} column. * * <p>To delete rows based on exact match with specific columns such as * {@link BlockedNumbers#COLUMN_ID} use * {@link android.content.ContentProvider#delete(Uri, String, String[])} with * {@link BlockedNumbers#CONTENT_URI} URI. * * <p> Note that if the {@link #canCurrentUserBlockNumbers} is {@code false} for the user * context {@code context}, this method will throw a {@link SecurityException}. * * @return the number of rows deleted in the blocked number provider as a result of unblock. */
@WorkerThread public static int unblock(Context context, String phoneNumber) { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_UNBLOCK, phoneNumber, null); return res.getInt(RES_NUM_ROWS_DELETED, 0); }
Checks if blocking numbers is supported for the current user.

Typically, blocking numbers is only supported for one user at a time.

Returns:true if the current user can block numbers.
/** * Checks if blocking numbers is supported for the current user. * <p> Typically, blocking numbers is only supported for one user at a time. * * @return {@code true} if the current user can block numbers. */
public static boolean canCurrentUserBlockNumbers(Context context) { try { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS, null, null); return res != null && res.getBoolean(RES_CAN_BLOCK_NUMBERS, false); } catch (NullPointerException | IllegalArgumentException ex) { // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if // either of these happen. Log.w(null, "canCurrentUserBlockNumbers: provider not ready."); return false; } }

The contract between the blockednumber provider and the system.

This is a wrapper over BlockedNumberContract that also manages the blocking behavior when the user contacts emergency services. See notifyEmergencyContact(Context) for details. All methods are protected by READ_BLOCKED_NUMBERS.READ_BLOCKED_NUMBERS and WRITE_BLOCKED_NUMBERS.WRITE_BLOCKED_NUMBERS appropriately which ensure that only system can access the methods defined here.

@hide
/** * <p> * The contract between the blockednumber provider and the system. * </p> * <p>This is a wrapper over {@link BlockedNumberContract} that also manages the blocking * behavior when the user contacts emergency services. See * {@link #notifyEmergencyContact(Context)} for details. All methods are protected by * {@link android.Manifest.permission#READ_BLOCKED_NUMBERS} and * {@link android.Manifest.permission#WRITE_BLOCKED_NUMBERS} appropriately which ensure that * only system can access the methods defined here. * </p> * @hide */
public static class SystemContract {
A protected broadcast intent action for letting components with READ_BLOCKED_NUMBERS.READ_BLOCKED_NUMBERS know that the block suppression status as returned by getBlockSuppressionStatus(Context) has been updated.
/** * A protected broadcast intent action for letting components with * {@link android.Manifest.permission#READ_BLOCKED_NUMBERS} know that the block suppression * status as returned by {@link #getBlockSuppressionStatus(Context)} has been updated. */
public static final String ACTION_BLOCK_SUPPRESSION_STATE_CHANGED = "android.provider.action.BLOCK_SUPPRESSION_STATE_CHANGED"; public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact"; public static final String METHOD_END_BLOCK_SUPPRESSION = "end_block_suppression"; public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number"; public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS = "get_block_suppression_status"; public static final String METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION = "should_show_emergency_call_notification"; public static final String RES_IS_BLOCKING_SUPPRESSED = "blocking_suppressed"; public static final String RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP = "blocking_suppressed_until_timestamp"; public static final String METHOD_GET_ENHANCED_BLOCK_SETTING = "get_enhanced_block_setting"; public static final String METHOD_SET_ENHANCED_BLOCK_SETTING = "set_enhanced_block_setting"; /* Preference key of block numbers not in contacts setting. */ public static final String ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED = "block_numbers_not_in_contacts_setting"; /* Preference key of block private number calls setting. */ public static final String ENHANCED_SETTING_KEY_BLOCK_PRIVATE = "block_private_number_calls_setting"; /* Preference key of block payphone calls setting. */ public static final String ENHANCED_SETTING_KEY_BLOCK_PAYPHONE = "block_payphone_calls_setting"; /* Preference key of block unknown calls setting. */ public static final String ENHANCED_SETTING_KEY_BLOCK_UNKNOWN = "block_unknown_calls_setting"; /* Preference key for whether should show an emergency call notification. */ public static final String ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION = "show_emergency_call_notification";
Notifies the provider that emergency services were contacted by the user.

This results in shouldSystemBlockNumber returning false independent of the contents of the provider for a duration defined by CarrierConfigManager.KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT the provider unless endBlockSuppression(Context) is called.

/** * Notifies the provider that emergency services were contacted by the user. * <p> This results in {@link #shouldSystemBlockNumber} returning {@code false} independent * of the contents of the provider for a duration defined by * {@link android.telephony.CarrierConfigManager#KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT} * the provider unless {@link #endBlockSuppression(Context)} is called. */
public static void notifyEmergencyContact(Context context) { try { context.getContentResolver().call( AUTHORITY_URI, METHOD_NOTIFY_EMERGENCY_CONTACT, null, null); } catch (NullPointerException | IllegalArgumentException ex) { // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if // either of these happen. Log.w(null, "notifyEmergencyContact: provider not ready."); } }
Notifies the provider to disable suppressing blocking. If emergency services were not contacted recently at all, calling this method is a no-op.
/** * Notifies the provider to disable suppressing blocking. If emergency services were not * contacted recently at all, calling this method is a no-op. */
public static void endBlockSuppression(Context context) { context.getContentResolver().call( AUTHORITY_URI, METHOD_END_BLOCK_SUPPRESSION, null, null); }
Returns true if phoneNumber is blocked taking notifyEmergencyContact(Context) into consideration. If emergency services have not been contacted recently and enhanced call blocking not been enabled, this method is equivalent to BlockedNumberContract.isBlocked(Context, String).
Params:
  • context – the context of the caller.
  • phoneNumber – the number to check.
  • extras – the extra attribute of the number.
Returns:true if should block the number. false otherwise.
/** * Returns {@code true} if {@code phoneNumber} is blocked taking * {@link #notifyEmergencyContact(Context)} into consideration. If emergency services * have not been contacted recently and enhanced call blocking not been enabled, this * method is equivalent to {@link #isBlocked(Context, String)}. * * @param context the context of the caller. * @param phoneNumber the number to check. * @param extras the extra attribute of the number. * @return {@code true} if should block the number. {@code false} otherwise. */
public static boolean shouldSystemBlockNumber(Context context, String phoneNumber, Bundle extras) { try { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras); return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false); } catch (NullPointerException | IllegalArgumentException ex) { // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if // either of these happen. Log.w(null, "shouldSystemBlockNumber: provider not ready."); return false; } }
Returns the current status of block suppression.
/** * Returns the current status of block suppression. */
public static BlockSuppressionStatus getBlockSuppressionStatus(Context context) { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_GET_BLOCK_SUPPRESSION_STATUS, null, null); return new BlockSuppressionStatus(res.getBoolean(RES_IS_BLOCKING_SUPPRESSED, false), res.getLong(RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP, 0)); }
Check whether should show the emergency call notification.
Params:
  • context – the context of the caller.
Returns:true if should show emergency call notification. false otherwise.
/** * Check whether should show the emergency call notification. * * @param context the context of the caller. * @return {@code true} if should show emergency call notification. {@code false} otherwise. */
public static boolean shouldShowEmergencyCallNotification(Context context) { try { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION, null, null); return res != null && res.getBoolean(RES_SHOW_EMERGENCY_CALL_NOTIFICATION, false); } catch (NullPointerException | IllegalArgumentException ex) { // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if // either of these happen. Log.w(null, "shouldShowEmergencyCallNotification: provider not ready."); return false; } }
Check whether the enhanced block setting is enabled.
Params:
Returns:true if the setting is enabled. false otherwise.
/** * Check whether the enhanced block setting is enabled. * * @param context the context of the caller. * @param key the key of the setting to check, can be * {@link #ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED} * {@link #ENHANCED_SETTING_KEY_BLOCK_PRIVATE} * {@link #ENHANCED_SETTING_KEY_BLOCK_PAYPHONE} * {@link #ENHANCED_SETTING_KEY_BLOCK_UNKNOWN} * {@link #ENHANCED_SETTING_KEY_EMERGENCY_CALL_NOTIFICATION_SHOWING} * @return {@code true} if the setting is enabled. {@code false} otherwise. */
public static boolean getEnhancedBlockSetting(Context context, String key) { Bundle extras = new Bundle(); extras.putString(EXTRA_ENHANCED_SETTING_KEY, key); try { final Bundle res = context.getContentResolver().call( AUTHORITY_URI, METHOD_GET_ENHANCED_BLOCK_SETTING, null, extras); return res != null && res.getBoolean(RES_ENHANCED_SETTING_IS_ENABLED, false); } catch (NullPointerException | IllegalArgumentException ex) { // The content resolver can throw an NPE or IAE; we don't want to crash Telecom if // either of these happen. Log.w(null, "getEnhancedBlockSetting: provider not ready."); return false; } }
Set the enhanced block setting enabled status.
Params:
/** * Set the enhanced block setting enabled status. * * @param context the context of the caller. * @param key the key of the setting to set, can be * {@link #ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED} * {@link #ENHANCED_SETTING_KEY_BLOCK_PRIVATE} * {@link #ENHANCED_SETTING_KEY_BLOCK_PAYPHONE} * {@link #ENHANCED_SETTING_KEY_BLOCK_UNKNOWN} * {@link #ENHANCED_SETTING_KEY_EMERGENCY_CALL_NOTIFICATION_SHOWING} * @param value the enabled statue of the setting to set. */
public static void setEnhancedBlockSetting(Context context, String key, boolean value) { Bundle extras = new Bundle(); extras.putString(EXTRA_ENHANCED_SETTING_KEY, key); extras.putBoolean(EXTRA_ENHANCED_SETTING_VALUE, value); context.getContentResolver().call(AUTHORITY_URI, METHOD_SET_ENHANCED_BLOCK_SETTING, null, extras); }
Represents the current status of SystemContract.shouldSystemBlockNumber(Context, String, Bundle). If emergency services have been contacted recently, isSuppressed is true, and blocking is disabled until the timestamp untilTimestampMillis.
/** * Represents the current status of * {@link #shouldSystemBlockNumber(Context, String, Bundle)}. If emergency services * have been contacted recently, {@link #isSuppressed} is {@code true}, and blocking * is disabled until the timestamp {@link #untilTimestampMillis}. */
public static class BlockSuppressionStatus { public final boolean isSuppressed;
Timestamp in milliseconds from epoch.
/** * Timestamp in milliseconds from epoch. */
public final long untilTimestampMillis; public BlockSuppressionStatus(boolean isSuppressed, long untilTimestampMillis) { this.isSuppressed = isSuppressed; this.untilTimestampMillis = untilTimestampMillis; } } } }