Call Screening(来电过滤) on Android N

转载请注明出处:http://blog.csdn.net/aaa111/article/details/72568691

 

之前在看Android官方文档系统的时候看到Android N 一系列新增和改变的特性,因为工作中负责的部分和通话有关,就尤其注意到了这个Call Screening。

下面来简单介绍一下Call Screening是什么,以及它在通话流程中起了哪些作用。

PS:一下代码全部来自Mokee mkn-mr1,

来自android官方的解释

Call Screening


Android 7.0 allows the default phone app to screen incoming calls. The phone app does this by implementing the new CallScreeningService, which allows the phone app to perform a number of actions based on an incoming call's Call.Details, such as:

  • Reject the incoming call
  • Do not allow the call to the call log
  • Do not show the user a notification for the call

For more information, see the reference documentation for CallScreeningService.

 

来电过滤(Call Screening)


Android 7.0 允许默认的手机应用过滤来电。手机应用执行此操作的方式是实现新的 CallScreeningService,该方法允许手机应用基于来电的 Call.Details 执行大量操作,例如:

  • 拒绝来电
  • 不允许来电到达通话记录
  • 不向用户显示来电通知

如需了解详细信息,请参阅可下载的 API 参考中的 android.telecom.CallScreeningService

 

 

读者可能会奇怪 Call Screening翻译成“呼叫筛选”可能更合适些,来电过滤 或许应该是IncomingCall filter的翻译啊(其实这也是有道理的,看了代码就知晓了)。

 

上面的文字有两个重点 based on an incoming call's Call.Details和 CallScreeningService。

应该是从Call.Details来判断需不需要过滤,先不看去判断哪些具体的条件,我们先看看CallScreeningService在代码中是什么样子的。

 

CallScreeningService

public abstract class CallScreeningService 
extends Service 

java.lang.Object
   ↳android.content.Context
    ↳android.content.ContextWrapper
     ↳android.app.Service
      ↳android.telecom.CallScreeningService

 


This service can be implemented by the default dialer (see getDefaultDialerPackage()) to allow or disallow incoming calls before they are shown to a user.

Below is an example manifest registration for a CallScreeningService.

 <service android:name="your.package.YourCallScreeningServiceImplementation"
          android:permission="android.permission.BIND_SCREENING_SERVICE">
      <intent-filter>
          <action android:name="android.telecom.CallScreeningService"/>
      </intent-filter>
 </service>

首先它是一个services,需要在拨号软件中实现,在AndroidManifest中的声明如上。

分析在源码中的使用

下面到源码中看这个是怎么使用的。

但是得到的第一个就是失望的消息,,

目前只有测试相关的代码cts/tests/tests/telecom/src/android/telecom/cts/MockCallScreeningService.java 注册了CallScreeningService,也就是说我们在Android N中并看不到这个功能的实际使用。

但是我们依然可以窥探一下CallScreeningService的功能以及在现有代码中的作用

PS:所有代码来自Mokee mkn-mr1

 
  1. public static class Builder {
  2. private boolean mShouldDisallowCall;
  3. private boolean mShouldRejectCall;
  4. private boolean mShouldSkipCallLog;
  5. private boolean mShouldSkipNotification;
  6.  
  7. /*
  8. * Sets whether the incoming call should be blocked.
  9. */
  10. public Builder setDisallowCall(boolean shouldDisallowCall) {
  11. mShouldDisallowCall = shouldDisallowCall;
  12. return this;
  13. }
  14.  
  15. /*
  16. * Sets whether the incoming call should be disconnected as if the user had manually
  17. * rejected it. This property should only be set to true if the call is disallowed.
  18. */
  19. public Builder setRejectCall(boolean shouldRejectCall) {
  20. mShouldRejectCall = shouldRejectCall;
  21. return this;
  22. }
  23.  
  24. /*
  25. * Sets whether the incoming call should not be displayed in the call log. This property
  26. * should only be set to true if the call is disallowed.
  27. */
  28. public Builder setSkipCallLog(boolean shouldSkipCallLog) {
  29. mShouldSkipCallLog = shouldSkipCallLog;
  30. return this;
  31. }
  32.  
  33. /*
  34. * Sets whether a missed call notification should not be shown for the incoming call.
  35. * This property should only be set to true if the call is disallowed.
  36. */
  37. public Builder setSkipNotification(boolean shouldSkipNotification) {
  38. mShouldSkipNotification = shouldSkipNotification;
  39. return this;
  40. }
  41.  
  42. public CallResponse build() {
  43. return new CallResponse(
  44. mShouldDisallowCall,
  45. mShouldRejectCall,
  46. mShouldSkipCallLog,
  47. mShouldSkipNotification);
  48. }
  49. }

四个重要的方法:setDisallowCall(), setRejectCall(), setSkipCallLog(), setSkipNotification(), 从这4个方法也可以大概知道,这个“来电过滤”能做的具体的事情是什么:1. 完全阻止来电(类似黑名单),2. 是否拒接来电, 3. 是否在CallLog中显示, 4. 是否要显示未接通知(这跟前面不就是一样的嘛),也就是说 可以通过这4个方法设置来电的提醒方式。

在cts代码中使用

再看一下在cts代码中的使用的

 
  1. private CallScreeningServiceCallbacks createCallbacks() {
  2. return new CallScreeningServiceCallbacks() {
  3. @Override
  4. public void onScreenCall(Call.Details callDetails) {
  5. mCallFound = true;
  6. CallScreeningService.CallResponse response =
  7. new CallScreeningService.CallResponse.Builder()
  8. .setDisallowCall(true)
  9. .setRejectCall(true)
  10. .setSkipCallLog(true)
  11. .setSkipNotification(true)
  12. .build();
  13. getService().respondToCall(callDetails, response);
  14. lock.release();
  15. }
  16. };
  17. }

2333 全是true、、

 

这个Call Screening其实可以看作是黑名但的补充功能(那么黑名单又叫做什么呢?Number Blocking-官方名号码屏蔽)。这么推测的话,这两者应该是协同工作的。

来电log

我们借用log来看一下来电的大体流程

 
  1. //正常来电
  2. 04-25 14:51:26.947 I/Telecom ( 2596): Event: Call TC@18: CREATED, null: TSI.aNIC@DOU
  3. 04-25 14:51:26.951 I/Telecom ( 2596): Event: Call TC@18: BIND_CS, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}: TSI.aNIC@DOU
  4. 04-25 14:51:26.962 I/Telecom ( 2596): Event: Call TC@18: CS_BOUND, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}: SBC.oSC@DOY
  5. 04-25 14:51:26.963 I/Telecom ( 2596): Event: Call TC@18: START_CONNECTION, tel:***********: SBC.oSC@DOY
  6. //初始化过滤器
  7. 04-25 14:51:26.988 I/Telecom ( 2596): Event: Call TC@18: FILTERING_INITIATED, null: CSW.hCCC@DOg
  8. //直接转至语音信箱初始化
  9. 04-25 14:51:26.988 I/Telecom ( 2596): Event: Call TC@18: DIRECT_TO_VM_INITIATED, null: CSW.hCCC@DOg
  10. 04-25 14:51:26.988 I/Telecom ( 2596): Event: Call TC@18: DIRECT_TO_VM_FINISHED, [Allow, logged, notified]: CSW.hCCC@DOg
  11. //Screening
  12. 04-25 14:51:26.989 I/Telecom ( 2596): Event: Call TC@18: SCREENING_SENT, null: CSW.hCCC@DOg
  13. //黑名单过滤初始化
  14. 04-25 14:51:26.989 I/Telecom ( 2596): Event: Call TC@18: BLOCK_CHECK_INITIATED, null: CSW.hCCC->ABCF.dIB@DOg_1
  15. //Call Screening的 三个参数 允许来电,记录到通话记录,显示通知
  16. 04-25 14:51:26.991 I/Telecom ( 2596): Event: Call TC@18: SCREENING_COMPLETED, [Allow, logged, notified]: CSW.hCCC@DOg
  17. //我们前面说过Call Screening并没有真正用起来
  18. 04-25 14:51:26.991 I/Telecom ( 2596): CallScreeningServiceFilter: There are no call screening services installed on this device.: CSW.hCCC@DOg
  19. 04-25 14:51:26.991 I/Telecom ( 2596): CallScreeningServiceFilter: Could not bind to call screening service: CSW.hCCC@DOg
  20. 04-25 14:51:27.007 I/Telecom ( 2596): Event: Call TC@18: BLOCK_CHECK_FINISHED, [Allow, logged, notified]: CSW.hCCC->ABCF.oPE@DOg_2
  21. //过滤结束
  22. 04-25 14:51:27.009 I/Telecom ( 2596): Event: Call TC@18: FILTERING_COMPLETED, [Allow, logged, notified]: CSW.hCCC->ABCF.oPE->ICF.oCFC@DOg_2_0
  23. //响铃 成功来电
  24. 04-25 14:51:27.011 I/Telecom ( 2596): Event: Call TC@18: SET_RINGING, successful incoming call: CSW.hCCC->ABCF.oPE->ICF.oCFC@DOg_2_0 //mk_in
  25. 04-25 14:51:27.016 I/Telecom ( 2596): Event: Call TC@18: START_RINGER, null: CSW.hCCC->ABCF.oPE->ICF.oCFC->CAMSM.pM_2002@DOg_2_0_1
  26. //未接
  27. 04-25 14:51:40.063 I/Telecom ( 2596): Event: Call TC@18: SET_DISCONNECTED, disconnected set explicitly> DisconnectCause [ Code: (MISSED) Label: () Description: () Reason: (INCOMING_MISSED) Tone: (-1) ]: CSW.sDc@DQI
  28. 04-25 14:51:40.099 I/Telecom ( 2596): Event: Call TC@18: DESTROYED, null: CSW.rC@DQk
  29.  
  30.  
  31. //黑名单号码来电
  32. 04-25 14:52:20.925 I/Telecom ( 2596): Event: Call TC@19: CREATED, null: TSI.aNIC@DRo
  33. 04-25 14:52:20.932 I/Telecom ( 2596): Event: Call TC@19: BIND_CS, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}: TSI.aNIC@DRo
  34. 04-25 14:52:20.950 I/Telecom ( 2596): Event: Call TC@19: CS_BOUND, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}: SBC.oSC@DRs
  35. 04-25 14:52:20.951 I/Telecom ( 2596): Event: Call TC@19: START_CONNECTION, tel:***********: SBC.oSC@DRs
  36. 04-25 14:52:20.973 I/Telecom ( 2596): Event: Call TC@19: CAPABILITY_CHANGE, Current: [[ sup_hld mut !v2a spd_aud]], Removed [[]], Added [[ sup_hld mut !v2a spd_aud]]: CSW.hCCC@DR0
  37. 04-25 14:52:20.974 I/Telecom ( 2596): Event: Call TC@19: FILTERING_INITIATED, null: CSW.hCCC@DR0
  38. 04-25 14:52:20.974 I/Telecom ( 2596): Event: Call TC@19: DIRECT_TO_VM_INITIATED, null: CSW.hCCC@DR0
  39. 04-25 14:52:20.975 I/Telecom ( 2596): Event: Call TC@19: SCREENING_SENT, null: CSW.hCCC@DR0
  40. 04-25 14:52:20.976 I/Telecom ( 2596): Event: Call TC@19: BLOCK_CHECK_INITIATED, null: CSW.hCCC->ABCF.dIB@DR0_0
  41. 04-25 14:52:20.980 I/Telecom ( 2596): Event: Call TC@19: SCREENING_COMPLETED, [Allow, logged, notified]: CSW.hCCC@DR0
  42. 04-25 14:52:20.981 I/Telecom ( 2596): Event: Call TC@19: DIRECT_TO_VM_FINISHED, [Allow, logged, notified]: TSI.aNIC->CILH.sL->CILH.oQC@DRo_1_0
  43. //黑名单阻止 可以看到输出有Reject
  44. 04-25 14:52:20.994 I/Telecom ( 2596): Event: Call TC@19: BLOCK_CHECK_FINISHED, [Reject]: CSW.hCCC->ABCF.oPE@DR0_1
  45. 04-25 14:52:20.995 I/Telecom ( 2596): Event: Call TC@19: FILTERING_COMPLETED, [Reject]: CSW.hCCC->ABCF.oPE->ICF.oCFC@DR0_1_0
  46. //响铃这一步 被block了
  47. 04-25 14:52:21.001 I/Telecom ( 2596): Event: Call TC@19: SET_RINGING, blocking call: CSW.hCCC->ABCF.oPE->ICF.oCFC@DR0_1_0 //mk_in
  48. 04-25 14:52:21.002 I/Telecom ( 2596): Event: Call TC@19: REQUEST_REJECT, null: CSW.hCCC->ABCF.oPE->ICF.oCFC@DR0_1_0
  49. //本地拒接
  50. 04-25 14:52:21.395 I/Telecom ( 2596): Event: Call TC@19: SET_DISCONNECTED, disconnected set explicitly> DisconnectCause [ Code: (REJECTED) Label: () Description: () Reason: (INCOMING_REJECTED) Tone: (-1) ]: CSW.sDc@DSI
  51. 04-25 14:52:21.400 I/Telecom ( 2596): Event: Call TC@19: DESTROYED, null: CSW.rC@DSM

PS: Event这个关键字是在M引入的,我只在前Android M MO的blog中提提到过,是专门记录关键流程点/事件的log,至于后面那一对缩写词还没去查。

 

从上面的log中看到Telecom Event log中已经加入了几种过滤相关的log,这也意味着虽然今天的主角虽然没有“暴露”出来,但是已经“安插”进去了。

来电流程中与来电过滤有关的部分

1. 来电 创建过滤器

packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

 
  1. public void onSuccessfulIncomingCallRewrite(Call incomingCall) {
  2. Log.d(this, "onSuccessfulIncomingCall");
  3. if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE)) {//如果是紧急号码回拨则不过滤
  4. Log.i(this, "Skipping call filtering due to ECBM");
  5. onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
  6. return;
  7. }
  8.  
  9. //过滤器s
  10. List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
  11. filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
  12. filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
  13. filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,//Call Screening
  14. mDefaultDialerManagerAdapter,
  15. new ParcelableCallUtils.Converter(), mLock));
  16. new IncomingCallFilter(mContext, this, incomingCall, mLock,//这三个过滤器都归属于IncomingCallFilter
  17. mTimeoutsAdapter, filters).performFiltering();//调用过滤方法
  18. }

2. 准备过滤

packages/services/Telecomm/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java

 
  1. public void performFiltering() {
  2. Log.event(mCall, Log.Events.FILTERING_INITIATED);
  3. for (CallFilter filter : mFilters) {//遍历过滤器调用起各自的过滤方法
  4. filter.startFilterLookup(mCall, this);
  5. }
  6. // synchronized to prevent a race on mResult and to enter into Telecom.
  7. mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) { // performFiltering time-out
  8. @Override
  9. public void loggedRun() {
  10. if (mIsPending) {
  11. Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
  12. Log.event(mCall, Log.Events.FILTERING_TIMED_OUT);
  13. mListener.onCallFilteringComplete(mCall, mResult);
  14. mIsPending = false;
  15. }
  16. }
  17. }.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
  18. }

 

3. 过滤器各自过滤

packages/services/Telecomm/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java

log我们看过了 Could not bind to call screening service,2333 没得搞,全剧终。

 
  1. @Override
  2. public void startFilterLookup(Call call, CallFilterResultCallback callback) {
  3. if (mHasFinished) {
  4. Log.w(this, "Attempting to reuse CallScreeningServiceFilter. Ignoring.");
  5. return;
  6. }
  7. Log.event(call, Log.Events.SCREENING_SENT);
  8. mCall = call;
  9. mCallback = callback;
  10. if (!bindService()) {
  11. Log.i(this, "Could not bind to call screening service");
  12. finishCallScreening();
  13. }
  14. }

 

因为系统Dialer没有应用这个功能嘛,所以其实到这里是断了的。那我们假如bindService()成功了呢?

 
  1. private void onServiceBound(ICallScreeningService service) {
  2. mService = service;
  3. try {
  4. mService.screenCall(new CallScreeningAdapter(),
  5. mParcelableCallUtilsConverter.toParcelableCall(
  6. mCall,
  7. false, /* includeVideoProvider */
  8. mPhoneAccountRegistrar));
  9. } catch (RemoteException e) {
  10. Log.e(this, e, "Failed to set the call screening adapter.");
  11. finishCallScreening();
  12. }
  13. }

frameworks/base/telecomm/java/android/telecom/CallScreeningService.java

 
  1. private final class CallScreeningBinder extends ICallScreeningService.Stub {
  2. @Override
  3. public void screenCall(ICallScreeningAdapter adapter, ParcelableCall call) {
  4. Log.v(this, "screenCall");
  5. SomeArgs args = SomeArgs.obtain();
  6. args.arg1 = adapter;
  7. args.arg2 = call;
  8. mHandler.obtainMessage(MSG_SCREEN_CALL, args).sendToTarget();
  9. }
  10. }

 

 
  1. private final Handler mHandler = new Handler(Looper.getMainLooper()) {
  2. @Override
  3. public void handleMessage(Message msg) {
  4. switch (msg.what) {
  5. case MSG_SCREEN_CALL:
  6. SomeArgs args = (SomeArgs) msg.obj;
  7. try {
  8. mCallScreeningAdapter = (ICallScreeningAdapter) args.arg1;
  9. onScreenCall(
  10. Call.Details.createFromParcelableCall((ParcelableCall) args.arg2));
  11. } finally {
  12. args.recycle();
  13. }
  14. break;
  15. }
  16. }
  17. };

过滤,具体内容要看哪里实现了这个方法

 
  1. /**
  2. * Called when a new incoming call is added.
  3. * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}
  4. * should be called to allow or disallow the call.
  5. *
  6. * @param callDetails Information about a new incoming call, see {@link Call.Details}.
  7. */
  8. public abstract void onScreenCall(Call.Details callDetails);

过滤完回调

 
  1. /**
  2. * Responds to the given call, either allowing it or disallowing it.
  3. *
  4. * @param callDetails The call to allow.
  5. * @param response The {@link CallScreeningService.CallResponse} which contains information
  6. * about how to respond to a call.
  7. */
  8. public final void respondToCall(Call.Details callDetails, CallResponse response) {
  9. try {
  10. if (response.getDisallowCall()) {
  11. mCallScreeningAdapter.disallowCall(
  12. callDetails.getTelecomCallId(),
  13. response.getRejectCall(),
  14. !response.getSkipCallLog(),
  15. !response.getSkipNotification());
  16. } else {
  17. mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
  18. }
  19. } catch (RemoteException e) {
  20. }
  21. }

packages/services/Telecomm/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java  

然后response.getDisallowCall()判断是否允许,接着处理结果

 
  1. private class CallScreeningAdapter extends ICallScreeningAdapter.Stub {
  2. @Override
  3. public void allowCall(String callId) {
  4. Log.startSession("CSCR.aC");
  5. long token = Binder.clearCallingIdentity();
  6. try {
  7. synchronized (mTelecomLock) {
  8. Log.d(this, "allowCall(%s)", callId);
  9. if (mCall != null && mCall.getId().equals(callId)) {
  10. mResult = new CallFilteringResult(
  11. true, // shouldAllowCall
  12. false, //shouldReject
  13. true, //shouldAddToCallLog
  14. true // shouldShowNotification
  15. );
  16. } else {
  17. Log.w(this, "allowCall, unknown call id: %s", callId);
  18. }
  19. finishCallScreening();
  20. }
  21. } finally {
  22. Binder.restoreCallingIdentity(token);
  23. Log.endSession();
  24. }
  25. }
  26.  
  27. @Override
  28. public void disallowCall(
  29. String callId,
  30. boolean shouldReject,
  31. boolean shouldAddToCallLog,
  32. boolean shouldShowNotification) {
  33. Log.startSession("CSCR.dC");
  34. long token = Binder.clearCallingIdentity();
  35. try {
  36. synchronized (mTelecomLock) {
  37. Log.i(this, "disallowCall(%s), shouldReject: %b, shouldAddToCallLog: %b, "
  38. + "shouldShowNotification: %b", callId, shouldReject,
  39. shouldAddToCallLog, shouldShowNotification);
  40. if (mCall != null && mCall.getId().equals(callId)) {
  41. mResult = new CallFilteringResult(
  42. false, // shouldAllowCall
  43. shouldReject, //shouldReject
  44. shouldAddToCallLog, //shouldAddToCallLog
  45. shouldShowNotification // shouldShowNotification
  46. );
  47. } else {
  48. Log.w(this, "disallowCall, unknown call id: %s", callId);
  49. }
  50. finishCallScreening();
  51. }
  52. } finally {
  53. Binder.restoreCallingIdentity(token);
  54. Log.endSession();
  55. }
  56. }
  57. }

 

packages/services/Telecomm/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java

回调至IncomingCallFilter,解绑service

 
  1. private void finishCallScreening() {
  2. if (!mHasFinished) {
  3. Log.event(mCall, Log.Events.SCREENING_COMPLETED, mResult);
  4. mCallback.onCallFilteringComplete(mCall, mResult);
  5.  
  6. if (mConnection != null) {
  7. // We still need to call unbind even if the service disconnected.
  8. mContext.unbindService(mConnection);//解绑
  9. mConnection = null;
  10. }
  11. mService = null;
  12. mHasFinished = true;
  13. }
  14. }

回调至IncomingCallFilter

packages/services/Telecomm/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java

 
  1. public void onCallFilteringComplete(Call call, CallFilteringResult result) {
  2. synchronized (mTelecomLock) { // synchronizing to prevent race on mResult
  3. mNumPendingFilters--;
  4. mResult = result.combine(mResult);
  5. if (mNumPendingFilters == 0) {
  6. // synchronized on mTelecomLock to enter into Telecom.
  7. mHandler.post(new Runnable("ICF.oCFC", mTelecomLock) {
  8. @Override
  9. public void loggedRun() {
  10. if (mIsPending) {
  11. Log.event(mCall, Log.Events.FILTERING_COMPLETED, mResult);
  12. mListener.onCallFilteringComplete(mCall, mResult);
  13. mIsPending = false;
  14. }
  15. }
  16. }.prepare());
  17. }
  18. }
  19. }

结果返回到CallsManager

如果允许call,

如果不允许call,再从result里面读shouldReject等,然后就对应开头部分提到的四种现象

 
  1.  
  2. @Override
  3. public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
  4. // Only set the incoming call as ringing if it isn't already disconnected. It is possible
  5. // that the connection service disconnected the call before it was even added to Telecom, in
  6. // which case it makes no sense to set it back to a ringing state.
  7. if (incomingCall.getState() != CallState.DISCONNECTED &&
  8. incomingCall.getState() != CallState.DISCONNECTING) {
  9. setCallState(incomingCall, CallState.RINGING,
  10. result.shouldAllowCall ? "successful incoming call" : "blocking call");
  11. } else {
  12. Log.i(this, "onCallFilteringCompleted: call already disconnected.");
  13. return;
  14. }
  15.  
  16. if (result.shouldAllowCall) {
  17. if (hasMaximumRingingCalls(incomingCall.getTargetPhoneAccount().getId())) {
  18. if (shouldSilenceInsteadOfReject(incomingCall)) {
  19. incomingCall.silence();
  20. } else {
  21. Log.i(this, "onCallFilteringCompleted: Call rejected! " +
  22. "Exceeds maximum number of ringing calls.");
  23. rejectCallAndLog(incomingCall);
  24. }
  25. } else if (hasMaximumDialingCalls()) {
  26. Log.i(this, "onCallFilteringCompleted: Call rejected! Exceeds maximum number of " +
  27. "dialing calls.");
  28. rejectCallAndLog(incomingCall);
  29. } else if (!isIncomingVideoCallAllowed(incomingCall, mContext)) {
  30. Toast.makeText(mContext, mContext.getResources().
  31. getString(R.string.incoming_call_failed_low_battery), Toast.LENGTH_LONG).
  32. show();
  33. rejectCallAndLog(incomingCall);
  34. } else {
  35. addCall(incomingCall);
  36. setActiveSubscription(incomingCall.getTargetPhoneAccount().getId());
  37. }
  38. } else {
  39. if (result.shouldReject) {
  40. Log.i(this, "onCallFilteringCompleted: blocked call, rejecting.");
  41. incomingCall.reject(false, null);
  42. }
  43. if (result.shouldAddToCallLog) {
  44. Log.i(this, "onCallScreeningCompleted: blocked call, adding to call log.");
  45. if (result.shouldShowNotification) {
  46. Log.w(this, "onCallScreeningCompleted: blocked call, showing notification.");
  47. }
  48. mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
  49. result.shouldShowNotification);
  50. } else if (result.shouldShowNotification) {
  51. Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
  52. mMissedCallNotifier.showMissedCallNotification(incomingCall);//未接通知
  53. }
  54. }
  55. }

 

看到这里还有两个问题需要解决:

1. Call Screening  内部是如何工作的,也就是它如何匹配号码的?

2. 我们怎么将一个号码添加到需要过滤的那个“列表”里?

 

 

 

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值