From 784f8d2b7e9ff16b05f3ead3dd3500e80419f5cd Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Fri, 25 Sep 2015 20:49:35 -0700 Subject: PhoneStateListener & ContentObserver for blocked calls. Add a phone state listener to attempt to silence the ringer earlier. Add ContentObserver which watches the call log. There is an instance created for each blocked calls. It will watch the call log for changes pertaining to a set of blocked numbers/times it keeps track of. If there is a call log entry which matches with that number and time, mark it as blocked. Bug: 24341350 Bug: 23944005 Change-Id: I5c40f722d777355140bf98f897d208bd0330e09c --- InCallUI/src/com/android/incallui/Call.java | 9 +- InCallUI/src/com/android/incallui/CallList.java | 5 + .../src/com/android/incallui/InCallPresenter.java | 105 ++++++++++++++++++++- .../com/android/incallui/InCallServiceImpl.java | 6 +- 4 files changed, 117 insertions(+), 8 deletions(-) (limited to 'InCallUI') diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java index c5971ff9f..e14db9b88 100644 --- a/InCallUI/src/com/android/incallui/Call.java +++ b/InCallUI/src/com/android/incallui/Call.java @@ -368,6 +368,8 @@ public class Call { private String mLastForwardedNumber; private String mCallSubject; + private long mTimeAddedMs; + private LogState mLogState = new LogState(); /** @@ -386,6 +388,8 @@ public class Call { updateFromTelecomCall(); mTelecomCall.registerCallback(mTelecomCallCallback); + + mTimeAddedMs = System.currentTimeMillis(); } public android.telecom.Call getTelecomCall() { @@ -513,6 +517,10 @@ public class Call { return mId; } + public long getTimeAddedMs() { + return mTimeAddedMs; + } + public String getNumber() { if (mTelecomCall == null) { return null; @@ -525,7 +533,6 @@ public class Call { } public void blockCall() { - // TODO: Some vibration still occurs. mTelecomCall.reject(false, null); setState(State.BLOCKED); } diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java index 231df0627..4f9e0af18 100644 --- a/InCallUI/src/com/android/incallui/CallList.java +++ b/InCallUI/src/com/android/incallui/CallList.java @@ -89,6 +89,7 @@ public class CallList { Trace.beginSection("onCallAdded"); final Call call = new Call(telecomCall); Log.d(this, "onCallAdded: callState=" + call.getState()); + // Check if call should be blocked. if (!call.isEmergencyCall() && call.getState() == Call.State.INCOMING) { final AtomicBoolean hasTimedOut = new AtomicBoolean(false); @@ -118,6 +119,10 @@ public class CallList { call.blockCall(); Log.d(this, "onCallAdded: " + Log.pii(call.getNumber()) + " blocked."); + + // Call back to the presenter so it can update the call log. + InCallPresenter.getInstance().onCallBlocked( + call.getNumber(), call.getTimeAddedMs()); } } }, null, call.getNumber(), countryIso)) { diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java index 032d096f8..d61a0ba87 100644 --- a/InCallUI/src/com/android/incallui/InCallPresenter.java +++ b/InCallUI/src/com/android/incallui/InCallPresenter.java @@ -22,24 +22,34 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Resources; +import android.database.ContentObserver; import android.graphics.Point; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; +import android.provider.CallLog; import android.telecom.DisconnectCause; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telecom.VideoProfile; import android.telephony.PhoneNumberUtils; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.view.Surface; import android.view.View; import android.view.Window; import android.view.WindowManager; +import com.android.contacts.common.GeoUtil; import com.android.contacts.common.interactions.TouchPointManager; import com.android.contacts.common.testing.NeededForTesting; import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette; +import com.android.dialer.calllog.CallLogAsyncTaskUtil; +import com.android.dialer.calllog.CallLogAsyncTaskUtil.OnCallLogQueryFinishedListener; +import com.android.dialer.database.FilteredNumberAsyncQueryHandler; +import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener; import com.android.incalluibind.ObjectFactory; import com.google.common.base.Preconditions; @@ -100,6 +110,7 @@ public class InCallPresenter implements CallList.Listener, private boolean mAccountSelectionCancelled = false; private InCallCameraManager mInCallCameraManager = null; private AnswerPresenter mAnswerPresenter = new AnswerPresenter(); + private FilteredNumberAsyncQueryHandler mFilteredQueryHandler; /** * Whether or not we are currently bound and waiting for Telecom to send us a new call. @@ -151,6 +162,80 @@ public class InCallPresenter implements CallList.Listener, } }; + private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + public void onCallStateChanged(int state, String incomingNumber) { + if (state == TelephonyManager.CALL_STATE_RINGING) { + // Check if the number is blocked, to silence the ringer. + String countryIso = GeoUtil.getCurrentCountryIso(mContext); + mFilteredQueryHandler.startBlockedQuery( + mOnCheckBlockedListener, null, incomingNumber, countryIso); + } + } + }; + + private final OnCheckBlockedListener mOnCheckBlockedListener = new OnCheckBlockedListener() { + @Override + public void onCheckComplete(final Integer id) { + if (id != null) { + // Silence the ringer now to prevent ringing and vibration before the call is + // terminated when Telecom attempts to add it. + getTelecomManager().silenceRinger(); + } + } + }; + + /** + * Observes the CallLog for changes so that when call log entries for blocked calls are added + * they can be marked with the blocked call type. Times out if too much time has passed. + */ + private class BlockedNumberContentObserver extends ContentObserver { + private static final int TIMEOUT_MS = 5000; + + private Handler mHandler; + private String mNumber; + private long mTimeAddedMs; + + public BlockedNumberContentObserver(Handler handler, String number, long timeAddedMs) { + super(handler); + + mHandler = handler; + mNumber = number; + mTimeAddedMs = timeAddedMs; + } + + @Override + public void onChange(boolean selfChange) { + CallLogAsyncTaskUtil.markCallAsBlocked(mContext, mNumber, mTimeAddedMs, + new OnCallLogQueryFinishedListener() { + @Override + public void onQueryFinished(boolean hasEntry) { + if (mContext != null && hasEntry) { + unregister(); + } + } + }); + } + + public void register() { + if (mContext != null) { + mContext.getContentResolver().registerContentObserver( + CallLog.CONTENT_URI, true, this); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + unregister(); + } + }, TIMEOUT_MS); + } + } + + private void unregister() { + if (mContext != null) { + mContext.getContentResolver().unregisterContentObserver(this); + } + } + }; + /** * Is true when the activity has been previously started. Some code needs to know not just if * the activity is currently up, but if it had been previously shown in foreground for this @@ -176,6 +261,7 @@ public class InCallPresenter implements CallList.Listener, private MaterialPalette mThemeColors; private TelecomManager mTelecomManager; + private TelephonyManager mTelephonyManager; public static synchronized InCallPresenter getInstance() { if (sInCallPresenter == null) { @@ -239,6 +325,11 @@ public class InCallPresenter implements CallList.Listener, VideoPauseController.getInstance().setUp(this); + mFilteredQueryHandler = new FilteredNumberAsyncQueryHandler(context.getContentResolver()); + mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + mCallList.setFilteredNumberQueryHandler(mFilteredQueryHandler); + Log.d(this, "Finished InCallPresenter.setUp"); } @@ -255,6 +346,7 @@ public class InCallPresenter implements CallList.Listener, mServiceConnected = false; attemptCleanup(); + mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); VideoPauseController.getInstance().tearDown(); } @@ -391,9 +483,8 @@ public class InCallPresenter implements CallList.Listener, * TODO: Consider listening to CallList callbacks to do this instead of receiving a direct * method invocation from InCallService. */ - public void onCallAdded(android.telecom.Call call) { - // Since a call has been added we are no longer waiting for Telecom to send us a - // call. + public void onCallAdded(final android.telecom.Call call) { + // Since a call has been added we are no longer waiting for Telecom to send us a call. setBoundAndWaitingForOutgoingCall(false, null); call.registerCallback(mCallCallback); } @@ -492,6 +583,14 @@ public class InCallPresenter implements CallList.Listener, } } + public void onCallBlocked(String number, long timeAddedMs) { + BlockedNumberContentObserver contentObserver = + new BlockedNumberContentObserver(new Handler(), number, timeAddedMs); + + // BlockedNumberContentObserver will unregister after successful log or timeout. + contentObserver.register(); + } + /** * Given the call list, return the state in which the in-call screen should be. */ diff --git a/InCallUI/src/com/android/incallui/InCallServiceImpl.java b/InCallUI/src/com/android/incallui/InCallServiceImpl.java index 6078d3d20..ee2ca1bbb 100644 --- a/InCallUI/src/com/android/incallui/InCallServiceImpl.java +++ b/InCallUI/src/com/android/incallui/InCallServiceImpl.java @@ -23,7 +23,7 @@ import android.telecom.Call; import android.telecom.CallAudioState; import android.telecom.InCallService; -import com.android.contacts.common.util.TelephonyManagerUtils; +import com.android.contacts.common.GeoUtil; import com.android.dialer.database.FilteredNumberAsyncQueryHandler; import java.util.Locale; @@ -48,9 +48,7 @@ public class InCallServiceImpl extends InCallService { @Override public void onCallAdded(Call call) { - final String countryIso = TelephonyManagerUtils.getCurrentCountryIso( - getApplicationContext(), - Locale.getDefault()); + final String countryIso = GeoUtil.getCurrentCountryIso(getApplicationContext()); CallList.getInstance().onCallAdded(call, countryIso); InCallPresenter.getInstance().onCallAdded(call); } -- cgit v1.2.3