diff options
author | Andrew Lee <anwlee@google.com> | 2015-10-04 05:24:43 -0700 |
---|---|---|
committer | Andrew Lee <anwlee@google.com> | 2015-10-06 12:01:35 -0700 |
commit | 4276408e68e70354ab4b2dfdc96f612e2a358485 (patch) | |
tree | 58081d89f109b63883e2baa899843e69cf45ff64 /InCallUI | |
parent | 8a4bd60ca1b35e2c6fa46fed16891f5be4be9f46 (diff) |
Refactor call blocking into InCallPresenter.
This retains CallList being context-independent, and consolidates
most of the logic. This makes InCallPresenter responsible for
calling into the CallList to add/remove/cleanup calls.
This will make it easier to hook in emergency call logic which needs
a Context to store the time an outgoing emergency call is made.
Also, remove the timeout runnable if the
BlockedNumberContentObserver unregisters after successfully
updating the call log.
Bug: 24418319
Change-Id: I6a203f5a260428f51e7965c73e3eee89edb949bd
Diffstat (limited to 'InCallUI')
5 files changed, 144 insertions, 91 deletions
diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java index e14db9b88..d1cb62374 100644 --- a/InCallUI/src/com/android/incallui/Call.java +++ b/InCallUI/src/com/android/incallui/Call.java @@ -20,6 +20,7 @@ import com.android.contacts.common.CallUtil; import com.android.contacts.common.testing.NeededForTesting; import com.android.dialer.util.IntentUtil; import com.android.incallui.Call.LogState; +import com.android.incallui.util.TelecomCallUtil; import android.content.Context; import android.hardware.camera2.CameraCharacteristics; @@ -522,14 +523,7 @@ public class Call { } public String getNumber() { - if (mTelecomCall == null) { - return null; - } - if (mTelecomCall.getDetails().getGatewayInfo() != null) { - return mTelecomCall.getDetails().getGatewayInfo() - .getOriginalAddress().getSchemeSpecificPart(); - } - return getHandle() == null ? null : getHandle().getSchemeSpecificPart(); + return TelecomCallUtil.getNumber(mTelecomCall); } public void blockCall() { @@ -738,9 +732,7 @@ public class Call { * repeated calls to isEmergencyNumber. */ private void updateEmergencyCallState() { - Uri handle = mTelecomCall.getDetails().getHandle(); - mIsEmergencyCall = PhoneNumberUtils.isEmergencyNumber( - handle == null ? "" : handle.getSchemeSpecificPart()); + mIsEmergencyCall = TelecomCallUtil.isEmergencyCall(mTelecomCall); } private void setModifyToVideoState(int newVideoState) { diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java index 4f9e0af18..bed1d607a 100644 --- a/InCallUI/src/com/android/incallui/CallList.java +++ b/InCallUI/src/com/android/incallui/CallList.java @@ -25,6 +25,7 @@ import android.telecom.PhoneAccount; import com.android.contacts.common.testing.NeededForTesting; import com.android.dialer.database.FilteredNumberAsyncQueryHandler; import com.android.dialer.logging.Logger; +import com.android.incallui.util.TelecomCallUtil; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; @@ -85,61 +86,11 @@ public class CallList { CallList() { } - public void onCallAdded(android.telecom.Call telecomCall, final String countryIso) { + public void onCallAdded(final android.telecom.Call telecomCall) { 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); - // Proceed with call if query is slow. - // Call may be blocked later when FilteredQueryHandler returns. - final Handler handler = new Handler(); - final Runnable runnable = new Runnable() { - public void run() { - hasTimedOut.set(true); - onCallAddedInternal(call); - } - }; - handler.postDelayed(runnable, BLOCK_QUERY_TIMEOUT_MS); - if (mFilteredQueryHandler.startBlockedQuery( - new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() { - @Override - public void onCheckComplete(final Integer id) { - if (!hasTimedOut.get()) { - handler.removeCallbacks(runnable); - } - if (id == null) { - if (!hasTimedOut.get()) { - onCallAddedInternal(call); - } - } else { - mFilteredQueryHandler.incrementFilteredCount(id); - 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)) { - Log.d(this, "onCallAdded: invalid number " - + call.getNumber() + ", skipping block checking"); - if (!hasTimedOut.get()) { - handler.removeCallbacks(runnable); - onCallAddedInternal(call); - } - } - } else { - onCallAddedInternal(call); - } - Trace.endSection(); - } - - private void onCallAddedInternal(Call call) { if (call.getState() == Call.State.INCOMING || call.getState() == Call.State.CALL_WAITING) { onIncoming(call, call.getCannedSmsResponses()); @@ -148,6 +99,7 @@ public class CallList { } call.logCallInitiationType(); + Trace.endSection(); } public void onCallRemoved(android.telecom.Call telecomCall) { diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java index d61a0ba87..59876c25f 100644 --- a/InCallUI/src/com/android/incallui/InCallPresenter.java +++ b/InCallUI/src/com/android/incallui/InCallPresenter.java @@ -50,6 +50,7 @@ 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.incallui.util.TelecomCallUtil; import com.android.incalluibind.ObjectFactory; import com.google.common.base.Preconditions; @@ -57,6 +58,7 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -75,6 +77,8 @@ public class InCallPresenter implements CallList.Listener, private static final String EXTRA_FIRST_TIME_SHOWN = "com.android.incallui.intent.extra.FIRST_TIME_SHOWN"; + private static final long BLOCK_QUERY_TIMEOUT_MS = 1000; + private static final Bundle EMPTY_EXTRAS = new Bundle(); private static InCallPresenter sInCallPresenter; @@ -195,6 +199,13 @@ public class InCallPresenter implements CallList.Listener, private String mNumber; private long mTimeAddedMs; + private Runnable mTimeoutRunnable = new Runnable() { + @Override + public void run() { + unregister(); + } + }; + public BlockedNumberContentObserver(Handler handler, String number, long timeAddedMs) { super(handler); @@ -220,17 +231,13 @@ public class InCallPresenter implements CallList.Listener, if (mContext != null) { mContext.getContentResolver().registerContentObserver( CallLog.CONTENT_URI, true, this); - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - unregister(); - } - }, TIMEOUT_MS); + mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MS); } } private void unregister() { if (mContext != null) { + mHandler.removeCallbacks(mTimeoutRunnable); mContext.getContentResolver().unregisterContentObserver(this); } } @@ -343,6 +350,8 @@ public class InCallPresenter implements CallList.Listener, */ public void tearDown() { Log.d(this, "tearDown"); + mCallList.clearOnDisconnect(); + mServiceConnected = false; attemptCleanup(); @@ -479,21 +488,85 @@ public class InCallPresenter implements CallList.Listener, bringToForeground(showDialpad); } - /** - * TODO: Consider listening to CallList callbacks to do this instead of receiving a direct - * method invocation from InCallService. - */ public void onCallAdded(final android.telecom.Call call) { + // Check if call should be blocked. + if (!TelecomCallUtil.isEmergencyCall(call) + && call.getState() == android.telecom.Call.STATE_RINGING) { + maybeBlockCall(call); + } else { + mCallList.onCallAdded(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); } /** - * TODO: Consider listening to CallList callbacks to do this instead of receiving a direct - * method invocation from InCallService. + * Checks whether a call should be blocked, and blocks it if so. Otherwise, it adds the call + * to the CallList so it can proceed as normal. There is a timeout, so if the function for + * checking whether a function is blocked does not return in a reasonable time, we proceed + * with adding the call anyways. */ + private void maybeBlockCall(final android.telecom.Call call) { + final String countryIso = GeoUtil.getCurrentCountryIso(mContext); + final String number = TelecomCallUtil.getNumber(call); + final long timeAdded = System.currentTimeMillis(); + + // Though AtomicBoolean's can be scary, don't fear, as in this case it is only used on the + // main UI thread. It is needed so we can change its value within different scopes, since + // that cannot be done with a final boolean. + final AtomicBoolean hasTimedOut = new AtomicBoolean(false); + + final Handler handler = new Handler(); + + // Proceed if the query is slow; the call may still be blocked after the query returns. + final Runnable runnable = new Runnable() { + public void run() { + hasTimedOut.set(true); + mCallList.onCallAdded(call); + } + }; + handler.postDelayed(runnable, BLOCK_QUERY_TIMEOUT_MS); + + OnCheckBlockedListener onCheckBlockedListener = new OnCheckBlockedListener() { + @Override + public void onCheckComplete(final Integer id) { + if (!hasTimedOut.get()) { + handler.removeCallbacks(runnable); + } + if (id == null) { + if (!hasTimedOut.get()) { + mCallList.onCallAdded(call); + } + } else { + call.reject(false, null); + Log.d(this, "checkForBlockedCall: " + Log.pii(number) + " blocked."); + + mFilteredQueryHandler.incrementFilteredCount(id); + + // Register observer to update the call log. + // BlockedNumberContentObserver will unregister after successful log or timeout. + BlockedNumberContentObserver contentObserver = + new BlockedNumberContentObserver(new Handler(), number, timeAdded); + contentObserver.register(); + } + } + }; + + boolean isInvalidNumber = mFilteredQueryHandler.startBlockedQuery( + onCheckBlockedListener, null, number, countryIso); + if (isInvalidNumber) { + Log.d(this, "checkForBlockedCall: invalid number, skipping block checking"); + if (!hasTimedOut.get()) { + handler.removeCallbacks(runnable); + mCallList.onCallAdded(call); + } + } + } + public void onCallRemoved(android.telecom.Call call) { + mCallList.onCallRemoved(call); call.unregisterCallback(mCallCallback); } @@ -583,14 +656,6 @@ 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 ee2ca1bbb..11202e7a3 100644 --- a/InCallUI/src/com/android/incallui/InCallServiceImpl.java +++ b/InCallUI/src/com/android/incallui/InCallServiceImpl.java @@ -23,11 +23,8 @@ import android.telecom.Call; import android.telecom.CallAudioState; import android.telecom.InCallService; -import com.android.contacts.common.GeoUtil; import com.android.dialer.database.FilteredNumberAsyncQueryHandler; -import java.util.Locale; - /** * Used to receive updates about calls from the Telecom component. This service is bound to * Telecom while there exist calls which potentially require UI. This includes ringing (incoming), @@ -48,14 +45,11 @@ public class InCallServiceImpl extends InCallService { @Override public void onCallAdded(Call call) { - final String countryIso = GeoUtil.getCurrentCountryIso(getApplicationContext()); - CallList.getInstance().onCallAdded(call, countryIso); InCallPresenter.getInstance().onCallAdded(call); } @Override public void onCallRemoved(Call call) { - CallList.getInstance().onCallRemoved(call); InCallPresenter.getInstance().onCallRemoved(call); } @@ -82,8 +76,6 @@ public class InCallServiceImpl extends InCallService { InCallPresenter.getInstance().onServiceBind(); InCallPresenter.getInstance().maybeStartRevealAnimation(intent); TelecomAdapter.getInstance().setInCallService(this); - CallList.getInstance().setFilteredNumberQueryHandler( - new FilteredNumberAsyncQueryHandler(getContentResolver())); return super.onBind(intent); } @@ -102,7 +94,6 @@ public class InCallServiceImpl extends InCallService { Log.v(this, "tearDown"); // Tear down the InCall system TelecomAdapter.getInstance().clearInCallService(); - CallList.getInstance().clearOnDisconnect(); InCallPresenter.getInstance().tearDown(); } diff --git a/InCallUI/src/com/android/incallui/util/TelecomCallUtil.java b/InCallUI/src/com/android/incallui/util/TelecomCallUtil.java new file mode 100644 index 000000000..53ecc29e9 --- /dev/null +++ b/InCallUI/src/com/android/incallui/util/TelecomCallUtil.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 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 com.android.incallui.util; + +import android.net.Uri; +import android.telecom.Call; +import android.telephony.PhoneNumberUtils; + +/** + * Class to provide a standard interface for obtaining information from the underlying + * android.telecom.Call. Much of this should be obtained through the incall.Call, but + * on occasion we need to interact with the telecom.Call directly (eg. call blocking, + * before the incall.Call has been created). + */ +public class TelecomCallUtil { + + // Whether the call handle is an emergency number. + public static boolean isEmergencyCall(Call call) { + Uri handle = call.getDetails().getHandle(); + return PhoneNumberUtils.isEmergencyNumber( + handle == null ? "" : handle.getSchemeSpecificPart()); + } + + public static String getNumber(Call call) { + if (call == null) { + return null; + } + if (call.getDetails().getGatewayInfo() != null) { + return call.getDetails().getGatewayInfo() + .getOriginalAddress().getSchemeSpecificPart(); + } + Uri handle = getHandle(call); + return handle == null ? null : handle.getSchemeSpecificPart(); + } + + public static Uri getHandle(Call call) { + return call == null ? null : call.getDetails().getHandle(); + } +} |