script-astra/Android/Sdk/sources/android-35/android/provider/BlockedNumbersManager.java

401 lines
18 KiB
Java
Raw Permalink Normal View History

2025-01-20 15:15:20 +00:00
/*
* Copyright (C) 2019 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 static android.provider.BlockedNumberContract.AUTHORITY_URI;
import static android.provider.BlockedNumberContract.EXTRA_ENHANCED_SETTING_KEY;
import static android.provider.BlockedNumberContract.EXTRA_ENHANCED_SETTING_VALUE;
import static android.provider.BlockedNumberContract.RES_BLOCK_STATUS;
import static android.provider.BlockedNumberContract.RES_ENHANCED_SETTING_IS_ENABLED;
import static android.provider.BlockedNumberContract.RES_SHOW_EMERGENCY_CALL_NOTIFICATION;
import static android.provider.BlockedNumberContract.STATUS_NOT_BLOCKED;
import static android.provider.BlockedNumberContract.SystemContract.METHOD_END_BLOCK_SUPPRESSION;
import static android.provider.BlockedNumberContract.SystemContract.METHOD_GET_BLOCK_SUPPRESSION_STATUS;
import static android.provider.BlockedNumberContract.SystemContract.METHOD_GET_ENHANCED_BLOCK_SETTING;
import static android.provider.BlockedNumberContract.SystemContract.METHOD_NOTIFY_EMERGENCY_CONTACT;
import static android.provider.BlockedNumberContract.SystemContract.METHOD_SET_ENHANCED_BLOCK_SETTING;
import static android.provider.BlockedNumberContract.SystemContract.METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION;
import static android.provider.BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER;
import static android.provider.BlockedNumberContract.SystemContract.RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP;
import static android.provider.BlockedNumberContract.SystemContract.RES_IS_BLOCKING_SUPPRESSED;
import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Bundle;
import android.telecom.Log;
import android.telecom.TelecomManager;
import com.android.server.telecom.flags.Flags;
/**
* Constants and methods to interact with the blocked numbers list. This class also serves as
* a mediator between the BlockedNumber provider and the system: it manages blocking behavior
* when the user contacts emergency services. Currently, this is only used internally by Telecom.
*
* Refer to {@link BlockedNumberContract} for more context.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public final class BlockedNumbersManager {
private static final String LOG_TAG = BlockedNumbersManager.class.getSimpleName();
private Context mContext;
/**
* @hide
*/
public BlockedNumbersManager(Context context) {
mContext = context;
}
/**
* 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()} has been updated.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final String ACTION_BLOCK_SUPPRESSION_STATE_CHANGED =
"android.provider.action.BLOCK_SUPPRESSION_STATE_CHANGED";
/**
* Preference key of block numbers not in contacts setting.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final String ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED =
"block_numbers_not_in_contacts_setting";
/**
* Preference key of block private number calls setting.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final String ENHANCED_SETTING_KEY_BLOCK_PRIVATE =
"block_private_number_calls_setting";
/**
* Preference key of block payphone calls setting.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final String ENHANCED_SETTING_KEY_BLOCK_PAYPHONE =
"block_payphone_calls_setting";
/**
* Preference key of block unknown calls setting.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final String ENHANCED_SETTING_KEY_BLOCK_UNKNOWN =
"block_unknown_calls_setting";
/**
* Preference key for whether should show an emergency call notification.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final String ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION =
"show_emergency_call_notification";
/**
* Preference key of block unavailable calls setting.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final String ENHANCED_SETTING_KEY_BLOCK_UNAVAILABLE =
"block_unavailable_calls_setting";
/**
* 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()} is called.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.READ_BLOCKED_NUMBERS,
android.Manifest.permission.WRITE_BLOCKED_NUMBERS
})
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public void notifyEmergencyContact() {
verifyBlockedNumbersPermission();
try {
Log.i(LOG_TAG, "notifyEmergencyContact; caller=%s", mContext.getOpPackageName());
mContext.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.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.READ_BLOCKED_NUMBERS,
android.Manifest.permission.WRITE_BLOCKED_NUMBERS
})
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public void endBlockSuppression() {
verifyBlockedNumbersPermission();
String caller = mContext.getOpPackageName();
Log.i(LOG_TAG, "endBlockSuppression: caller=%s", caller);
mContext.getContentResolver().call(AUTHORITY_URI, METHOD_END_BLOCK_SUPPRESSION, null, null);
}
/**
* Returns {@code true} if {@code phoneNumber} is blocked taking
* {@link #notifyEmergencyContact()} into consideration. If emergency services
* have not been contacted recently and enhanced call blocking not been enabled, this
* method is equivalent to {@link BlockedNumberContract#isBlocked(Context, String)}.
*
* @param phoneNumber the number to check.
* @param numberPresentation the presentation code associated with the call.
* @param isNumberInContacts indicates if the provided number exists as a contact.
* @return result code indicating if the number should be blocked, and if so why.
* Valid values are: {@link BlockedNumberContract#STATUS_NOT_BLOCKED},
* {@link BlockedNumberContract#STATUS_BLOCKED_IN_LIST},
* {@link BlockedNumberContract#STATUS_BLOCKED_NOT_IN_CONTACTS},
* {@link BlockedNumberContract#STATUS_BLOCKED_PAYPHONE},
* {@link BlockedNumberContract#STATUS_BLOCKED_RESTRICTED},
* {@link BlockedNumberContract#STATUS_BLOCKED_UNKNOWN_NUMBER}.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.READ_BLOCKED_NUMBERS,
android.Manifest.permission.WRITE_BLOCKED_NUMBERS
})
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public int shouldSystemBlockNumber(@NonNull String phoneNumber,
@TelecomManager.Presentation int numberPresentation, boolean isNumberInContacts) {
verifyBlockedNumbersPermission();
try {
String caller = mContext.getOpPackageName();
Bundle extras = new Bundle();
extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, numberPresentation);
extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST, isNumberInContacts);
final Bundle res = mContext.getContentResolver().call(AUTHORITY_URI,
METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
int blockResult = res != null ? res.getInt(RES_BLOCK_STATUS, STATUS_NOT_BLOCKED) :
BlockedNumberContract.STATUS_NOT_BLOCKED;
Log.d(LOG_TAG, "shouldSystemBlockNumber: number=%s, caller=%s, result=%s",
Log.piiHandle(phoneNumber), caller,
BlockedNumberContract.SystemContract.blockStatusToString(blockResult));
return blockResult;
} 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 BlockedNumberContract.STATUS_NOT_BLOCKED;
}
}
/**
* @return The current status of block suppression.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.READ_BLOCKED_NUMBERS,
android.Manifest.permission.WRITE_BLOCKED_NUMBERS
})
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public @NonNull BlockSuppressionStatus getBlockSuppressionStatus() {
verifyBlockedNumbersPermission();
final Bundle res = mContext.getContentResolver().call(
AUTHORITY_URI, METHOD_GET_BLOCK_SUPPRESSION_STATUS, null, null);
BlockSuppressionStatus blockSuppressionStatus = new BlockSuppressionStatus(
res.getBoolean(RES_IS_BLOCKING_SUPPRESSED, false),
res.getLong(RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP, 0));
Log.d(LOG_TAG, "getBlockSuppressionStatus: caller=%s, status=%s",
mContext.getOpPackageName(), blockSuppressionStatus);
return blockSuppressionStatus;
}
/**
* Check whether should show the emergency call notification.
*
* @return {@code true} if should show emergency call notification. {@code false} otherwise.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.READ_BLOCKED_NUMBERS,
android.Manifest.permission.WRITE_BLOCKED_NUMBERS
})
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public boolean shouldShowEmergencyCallNotification() {
verifyBlockedNumbersPermission();
try {
final Bundle res = mContext.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.
*
* @param key the key of the setting to check, can be
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNAVAILABLE}
* {@link BlockedNumberContract.SystemContract
* #ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION}
* @return {@code true} if the setting is enabled. {@code false} otherwise.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.READ_BLOCKED_NUMBERS,
android.Manifest.permission.WRITE_BLOCKED_NUMBERS
})
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public boolean getBlockedNumberSetting(@NonNull String key) {
verifyBlockedNumbersPermission();
Bundle extras = new Bundle();
extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
try {
final Bundle res = mContext.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.
*
* @param key the key of the setting to set, can be
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN}
* {@link BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNAVAILABLE}
* {@link BlockedNumberContract.SystemContract
* #ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION}
* @param value the enabled statue of the setting to set.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.READ_BLOCKED_NUMBERS,
android.Manifest.permission.WRITE_BLOCKED_NUMBERS
})
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public void setBlockedNumberSetting(@NonNull String key, boolean value) {
verifyBlockedNumbersPermission();
Bundle extras = new Bundle();
extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
extras.putBoolean(EXTRA_ENHANCED_SETTING_VALUE, value);
mContext.getContentResolver().call(AUTHORITY_URI, METHOD_SET_ENHANCED_BLOCK_SETTING,
null, extras);
}
/**
* Represents the current status of
* {@link #shouldSystemBlockNumber(String, int, boolean)}. If emergency services
* have been contacted recently, {@link #mIsSuppressed} is {@code true}, and blocking
* is disabled until the timestamp {@link #mUntilTimestampMillis}.
* @hide
*/
@SystemApi
@FlaggedApi(Flags.FLAG_TELECOM_MAINLINE_BLOCKED_NUMBERS_MANAGER)
public static final class BlockSuppressionStatus {
/**
* Indicates if block suppression is enabled.
*/
private boolean mIsSuppressed;
/**
* Timestamp in milliseconds from epoch.
*/
private long mUntilTimestampMillis;
public BlockSuppressionStatus(boolean isSuppressed, long untilTimestampMillis) {
this.mIsSuppressed = isSuppressed;
this.mUntilTimestampMillis = untilTimestampMillis;
}
@Override
public String toString() {
return "[BlockSuppressionStatus; isSuppressed=" + mIsSuppressed + ", until="
+ mUntilTimestampMillis + "]";
}
/**
* @return mIsSuppressed Indicates whether or not block suppression is enabled.
*/
public boolean getIsSuppressed() {
return mIsSuppressed;
}
/**
* @return mUntilTimestampMillis The timestamp until which block suppression would be
* enabled for
*/
public long getUntilTimestampMillis() {
return mUntilTimestampMillis;
}
}
/**
* Verifies that the caller holds both the
* {@link android.Manifest.permission#READ_BLOCKED_NUMBERS} permission and the
* {@link android.Manifest.permission#WRITE_BLOCKED_NUMBERS} permission.
*
* @throws SecurityException if the caller is missing the necessary permissions
*/
private void verifyBlockedNumbersPermission() {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_BLOCKED_NUMBERS,
"Caller does not have the android.permission.READ_BLOCKED_NUMBERS permission");
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_BLOCKED_NUMBERS,
"Caller does not have the android.permission.WRITE_BLOCKED_NUMBERS permission");
}
}