【目标】

实现 8.1 中黑名单拦截功能

【实现】

涉及到的文件

frameworks/base/api/current.txt
frameworks/base/api/system-current.txt

frameworks/base/core/java/android/provider/BlockedNumberContract.java
frameworks/opt/telephony/src/java/com/android/internal/telephony/BlockChecker.java
build/target/product/core.mk
packages/providers/BlockedNumberProvider

前两个文件可忽略,需要你在添加 BlockedNumberContract.java 后进行 make update-api 编译操作 api 中的内容就会自动更新,这样其它类调用编译时才能不报错

BlockedNumberContract.java

/** 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;/*** <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* </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 */public static final String AUTHORITY = "com.android.blockednumber";/** 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.*/public static class BlockedNumbers {private BlockedNumbers() {}/*** 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 {@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 {@link #CONTENT_URI}.*/public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";/*** Auto-generated ID field which monotonically increases.* <p>TYPE: long</p>*/public static final String COLUMN_ID = "_id";/*** 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 {@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 */public static final String METHOD_IS_BLOCKED = "is_blocked";/** @hide */public static final String METHOD_UNBLOCK= "unblock";/** @hide */public static final String RES_NUMBER_IS_BLOCKED = "blocked";/** @hide */public static final String RES_NUM_ROWS_DELETED = "num_deleted";/** @hide */public static final String METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS ="can_current_user_block_numbers";/** @hide */public static final String RES_CAN_BLOCK_NUMBERS = "can_block";/*** 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.*/@WorkerThreadpublic static boolean isBlocked(Context context, String phoneNumber) {//just check number is blockedfinal Bundle res = context.getContentResolver().call(AUTHORITY_URI, METHOD_IS_BLOCKED, phoneNumber, null);return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);}/*** 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.*/@WorkerThreadpublic 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.* <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) {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);}/*** <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* {@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 RES_IS_BLOCKING_SUPPRESSED = "blocking_suppressed";public static final String RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP ="blocking_suppressed_until_timestamp";/*** 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* the provider unless {@link #endBlockSuppression(Context)} is called.*/public static void notifyEmergencyContact(Context context) {context.getContentResolver().call(AUTHORITY_URI, METHOD_NOTIFY_EMERGENCY_CONTACT, null, null);}/*** 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 {@code true} if {@code phoneNumber} is blocked taking* {@link #notifyEmergencyContact(Context)} into consideration. If emergency services have* not been contacted recently, this method is equivalent to* {@link #isBlocked(Context, String)}.*/public static boolean shouldSystemBlockNumber(Context context, String phoneNumber) {final Bundle res = context.getContentResolver().call(AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, null);return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);}/*** 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));}/*** Represents the current status of {@link #shouldSystemBlockNumber(Context, String)}. 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.*/public final long untilTimestampMillis;public BlockSuppressionStatus(boolean isSuppressed, long untilTimestampMillis) {this.isSuppressed = isSuppressed;this.untilTimestampMillis = untilTimestampMillis;}}}
}

执行完 make update-api 成功后,再继续添加 BlockChecker

BlockChecker.java

package com.android.internal.telephony;import android.content.Context;
import android.provider.BlockedNumberContract;
import android.telephony.Rlog;/*** {@hide} Checks for blocked phone numbers against {@link BlockedNumberContract}*/
public class BlockChecker {private static final String TAG = "BlockChecker";private static final boolean VDBG = false; // STOPSHIP if true./*** Returns {@code true} if {@code phoneNumber} is blocked.* <p>* This method catches all underlying exceptions to ensure that this method never throws any* exception.*/public static boolean isBlocked(Context context, String phoneNumber) {boolean isBlocked = false;long startTimeNano = System.nanoTime();try {if (BlockedNumberContract.SystemContract.shouldSystemBlockNumber(context, phoneNumber)) {Rlog.d(TAG, phoneNumber + " is blocked.");isBlocked = true;}} catch (Exception e) {Rlog.e(TAG, "Exception checking for blocked number: " + e);}android.util.Log.e("InterceptInfos"," BlockChecker check phoneNumber="+phoneNumber + "  isBlocked="+isBlocked);int durationMillis = (int) ((System.nanoTime() - startTimeNano) / 1000000);if (durationMillis > 500 || VDBG) {Rlog.d(TAG, "Blocked number lookup took: " + durationMillis + " ms.");}return isBlocked;}
}

添加 BlockChecker 后,执行 mmm frameworks/opt/telephony 看下是否能通过

继续在 build/target/product/core.mk 中增加 BlockedNumberProvider 编译项


PRODUCT_PACKAGES += \BasicDreams \BlockedNumberProvider \Browser \Calculator \Calendar \CalendarProvider \

最后在 packages/providers/ 下增加 BlockedNumberProvider 源码,

代码已上传至 github

【下一篇】

Android6.0 源码添加黑名单拦截电话和短信记录

Android6.0 源码增加黑名单功能相关推荐

  1. Android6.0 源码添加黑名单拦截电话和短信记录

    [目标] 在上一篇 Android6.0 源码增加黑名单功能 的基础上增加黑名单和短信拦截记录 [实现] 黑名单数据库和拦截记录数据库上一篇已经增加完成,这就需要我们在电话和短信分发的地方去判断号码是 ...

  2. Android6.0 源码修改之Settings音量调节界面增加通话音量调节

    Android6.0 源码修改之Settings音量调节界面增加通话音量调节 前言 今天客户提了个需求,因为我们的设备在正常情况下无法调节通话音量,只有在打电话过程中,按物理音量加减键才能出现调节通话 ...

  3. android6.0源码分析之AMS服务源码分析

    activitymanagerservice服务源码分析 1.ActivityManagerService概述 ActivityManagerService(以下简称AMS)作为Android中最核心 ...

  4. android6.0源码分析之Zygote进程分析

    在android6.0源码分析之Runtime的初始化一文中,对Zygote进程的初期的Runtime初始化过程进行了分析,在Runtime启动结束后,会对Zygote进程进行初始化,其它Java进程 ...

  5. Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮...

    Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮 前言 之前写过屏蔽系统导航栏功能的文章,具体可看Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP) ...

  6. Android源码定制(1)——Android6.0源码编译

    一.前言 最近在研究Xposed框架定制,恰好又看到看雪上两个大佬关于源码定制和Xposed源码定制的帖子,所以尝试基于Android6.0版本,详细记录一下从源码下载到Xposed框架定制的全过程. ...

  7. android6.0源码分析之Runtime的初始化

    Android运行时作为android架构的一部分,起着非常重要的作用,它和核心库(Core Libraries)组成了Android运行时库层.本文将依据android源码对AndroidRunti ...

  8. android6.0源码分析之Camera2 HAL分析

    1.Camera HAL的初始化 Camera HAL的初始加载是在Native的CameraService初始化流程中的,而CameraService初始化是在Main_mediaServer.cp ...

  9. android6.0源码分析之Camera API2.0下的Preview(预览)流程分析

    1.Camera2 preview的应用层流程分析 preview流程都是从startPreview开始的,所以来看startPreview方法的代码: <code class="hl ...

最新文章

  1. 机器学习和计算机视觉的20大图像数据集
  2. 软件工程实训有必要吗_软件工程实训报告的总结.docx
  3. 20145204 张亚军《信息安全系统设计基础》第10周学习总结
  4. C#中的9个“黑魔法”与“骚操作”
  5. python应声虫程序_Python编程基础
  6. php文件夹转换网页,PHP转换文件夹下所有文件的编码 适合发布网站的其他编码版本...
  7. 最大乘积java_《算法入门经典》-最大乘积(java实现)
  8. Atitit 战略之道 attilax著
  9. prompt的使用oracle,SQL Prompt怎么用?SQL Prompt使用教程
  10. Android中应用程序获得系统签名权限(platform.x509.pem platform.pk8)下载地址
  11. 领导力培训知识点汇总及感悟-1
  12. NHibernate]集合类(Collections)映射
  13. Android Alarm闹钟
  14. 开关电源模块 遥控开/关电路
  15. rdesktop安装教程
  16. C++第2次实验作业
  17. Django使用图片验证码加邮箱或手机号登录
  18. php八字喜用神实现博客,八字喜用神测算方法
  19. Linux export 命令及如何删除export设置的环境变量
  20. 2023五一建模A题完整版本【原创首发】

热门文章

  1. 数值积分的python实现——NewtonCotes、复化求积、Romberg、richardson递推
  2. SQL条件IF函数(MySql)
  3. 安卓模拟器监控软件使用教程
  4. 西电计算机原理与系统组装实验报告,西电计组实验报告.docx
  5. 安卓手机卡顿怎么解决_硬件与软件的赛跑导致苹果系统闪退,安卓手机卡顿,可你们选谁呢...
  6. Spring详解 | IOC_DI_Bean | 无知的我费曼笔记(图文排版无水印)
  7. HTML简单又好用的几种颜色!
  8. iOS 小组件 widget group id, app group, 数据共享
  9. Linux 初始化root密码
  10. 云南tc焊接机器人价格_青海全自动焊接机器人批发价格优惠报价 国巨智能科技厂家直销...