summaryrefslogtreecommitdiff
path: root/InCallUI
diff options
context:
space:
mode:
authorAndrew Lee <anwlee@google.com>2015-10-04 05:24:43 -0700
committerAndrew Lee <anwlee@google.com>2015-10-06 12:01:35 -0700
commit4276408e68e70354ab4b2dfdc96f612e2a358485 (patch)
tree58081d89f109b63883e2baa899843e69cf45ff64 /InCallUI
parent8a4bd60ca1b35e2c6fa46fed16891f5be4be9f46 (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')
-rw-r--r--InCallUI/src/com/android/incallui/Call.java14
-rw-r--r--InCallUI/src/com/android/incallui/CallList.java54
-rw-r--r--InCallUI/src/com/android/incallui/InCallPresenter.java105
-rw-r--r--InCallUI/src/com/android/incallui/InCallServiceImpl.java9
-rw-r--r--InCallUI/src/com/android/incallui/util/TelecomCallUtil.java53
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();
+ }
+}