Remove hidden Telephony API usages from Telecom
Inline utility methods from BlockChecker and
AsyncEmergencyContactNotifier, and use the new API from
TelephonyRegistryManager in PhoneStateBroadcaster.
Also fix a flaky test
Bug: 141576016
Fixes: 144264937
Test: unit, cts
Change-Id: I6108d0e1c97f15b096c8b07f529edf5c3a7ee058
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 63fe1f4..9e8cf22 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -46,6 +46,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.BlockedNumberContract;
import android.provider.BlockedNumberContract.SystemContract;
import android.provider.CallLog.Calls;
import android.provider.Settings;
@@ -111,6 +112,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -1993,7 +1995,9 @@
}
if (call.isEmergencyCall()) {
- new AsyncEmergencyContactNotifier(mContext).execute();
+ Executors.defaultThreadFactory().newThread(() ->
+ BlockedNumberContract.SystemContract.notifyEmergencyContact(mContext))
+ .start();
}
final boolean requireCallCapableAccountByHandle = mContext.getResources().getBoolean(
@@ -4800,6 +4804,10 @@
}
}
+ public Context getContext() {
+ return mContext;
+ }
+
/**
* Determines if there is an ongoing emergency call. This can be either an outgoing emergency
* call, or a number which has been identified by the number as an emergency call.
diff --git a/src/com/android/server/telecom/PhoneStateBroadcaster.java b/src/com/android/server/telecom/PhoneStateBroadcaster.java
index 533c81c..f2531ed 100644
--- a/src/com/android/server/telecom/PhoneStateBroadcaster.java
+++ b/src/com/android/server/telecom/PhoneStateBroadcaster.java
@@ -16,12 +16,9 @@
package com.android.server.telecom;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.telecom.Log;
import android.telephony.TelephonyManager;
-
-import com.android.internal.telephony.ITelephonyRegistry;
+import android.telephony.TelephonyRegistryManager;
/**
* Send a {@link TelephonyManager#ACTION_PHONE_STATE_CHANGED} broadcast when the call state
@@ -30,13 +27,12 @@
final class PhoneStateBroadcaster extends CallsManagerListenerBase {
private final CallsManager mCallsManager;
- private final ITelephonyRegistry mRegistry;
+ private final TelephonyRegistryManager mRegistry;
private int mCurrentState = TelephonyManager.CALL_STATE_IDLE;
public PhoneStateBroadcaster(CallsManager callsManager) {
mCallsManager = callsManager;
- mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
- "telephony.registry"));
+ mRegistry = callsManager.getContext().getSystemService(TelephonyRegistryManager.class);
if (mRegistry == null) {
Log.w(this, "TelephonyRegistry is null");
}
@@ -112,13 +108,9 @@
callHandle = call.getHandle().getSchemeSpecificPart();
}
- try {
- if (mRegistry != null) {
- mRegistry.notifyCallStateForAllSubs(phoneState, callHandle);
- Log.i(this, "Broadcasted state change: %s", mCurrentState);
- }
- } catch (RemoteException e) {
- Log.w(this, "RemoteException when notifying TelephonyRegistry of call state change.");
+ if (mRegistry != null) {
+ mRegistry.notifyCallStateChangedForAllSubscriptions(phoneState, callHandle);
+ Log.i(this, "Broadcasted state change: %s", mCurrentState);
}
}
}
diff --git a/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java b/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
index 4a5ac60..1a641f0 100644
--- a/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
+++ b/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
@@ -18,27 +18,51 @@
import android.content.Context;
import android.os.Bundle;
+import android.provider.BlockedNumberContract;
+import android.telecom.Log;
import com.android.internal.telephony.BlockChecker;
public class BlockCheckerAdapter {
+ private static final String TAG = BlockCheckerAdapter.class.getSimpleName();
+
public BlockCheckerAdapter() { }
/**
- * Check whether the number is blocked.
+ * Returns the call blocking status for the {@code phoneNumber}.
+ * <p>
+ * This method catches all underlying exceptions to ensure that this method never throws any
+ * exception.
*
* @param context the context of the caller.
- * @param number the number to check.
+ * @param phoneNumber the number to check.
* @param extras the extra attribute of the number.
* @return result code indicating if the number should be blocked, and if so why.
- * Valid values are: {@link android.provider.BlockedNumberContract#STATUS_NOT_BLOCKED},
- * {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_IN_LIST},
- * {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_NOT_IN_CONTACTS},
- * {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_PAYPHONE},
- * {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_RESTRICTED},
- * {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_UNKNOWN_NUMBER}.
+ * Valid values are: {@link BlockedNumberContract#STATUS_NOT_BLOCKED},
+ * {@link BlockedNumberContract#STATUS_BLOCKED_IN_LIST},
+ * {@link BlockedNumberContract#STATUS_BLOCKED_NOT_IN_CONTACTS},
+ * {@link BlockedNumberContract#STATUS_BLOCKED_PAYPHONE},
+ * {@link BlockedNumberContract#STATUS_BLOCKED_RESTRICTED},
+ * {@link BlockedNumberContract#STATUS_BLOCKED_UNKNOWN_NUMBER}.
*/
- public int getBlockStatus(Context context, String number, Bundle extras) {
- return BlockChecker.getBlockStatus(context, number, extras);
+ public int getBlockStatus(Context context, String phoneNumber, Bundle extras) {
+ int blockStatus = BlockedNumberContract.STATUS_NOT_BLOCKED;
+ long startTimeNano = System.nanoTime();
+
+ try {
+ blockStatus = BlockedNumberContract.SystemContract.shouldSystemBlockNumber(
+ context, phoneNumber, extras);
+ if (blockStatus != BlockedNumberContract.STATUS_NOT_BLOCKED) {
+ Log.d(TAG, phoneNumber + " is blocked.");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, e, "Exception checking for blocked number");
+ }
+
+ int durationMillis = (int) ((System.nanoTime() - startTimeNano) / 1000000);
+ if (durationMillis > 500 || Log.isLoggable(android.util.Log.DEBUG)) {
+ Log.d(TAG, "Blocked number lookup took: " + durationMillis + " ms.");
+ }
+ return blockStatus;
}
}
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 5c7b357..322a3c2 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -377,10 +377,13 @@
waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
TEST_TIMEOUT);
assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
+
+ CallerInfo sendToVoicemailCallerInfo = new CallerInfo();
+ sendToVoicemailCallerInfo.shouldSendToVoicemail = true;
+ sendToVoicemailCallerInfo.contactExists = true;
+ mCallerInfoAsyncQueryFactoryFixture.setResponse(sendToVoicemailCallerInfo);
for (CallerInfoAsyncQueryFactoryFixture.Request request :
mCallerInfoAsyncQueryFactoryFixture.mRequests) {
- CallerInfo sendToVoicemailCallerInfo = new CallerInfo();
- sendToVoicemailCallerInfo.shouldSendToVoicemail = true;
request.replyWithCallerInfo(sendToVoicemailCallerInfo);
}
diff --git a/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java b/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java
index c469dbc..68db09c 100644
--- a/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java
+++ b/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java
@@ -27,7 +27,9 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Controls a test {@link CallerInfoAsyncQueryFactory} to abstract away the asynchronous retrieval
@@ -58,16 +60,24 @@
r.mCookie = cookie;
r.mListener = listener;
mRequests.add(r);
+ if (mStoredResponse != null) {
+ listener.onQueryComplete(token, cookie, mStoredResponse);
+ }
return Mockito.mock(CallerInfoAsyncQuery.class);
}
};
final List<Request> mRequests = Collections.synchronizedList(new ArrayList<Request>());
+ private CallerInfo mStoredResponse;
public CallerInfoAsyncQueryFactoryFixture() throws Exception {
Log.i(this, "Creating ...");
}
+ public void setResponse(CallerInfo callerInfo) {
+ mStoredResponse = callerInfo;
+ }
+
@Override
public CallerInfoAsyncQueryFactory getTestDouble() {
return mCallerInfoAsyncQueryFactory;
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index dcd0607..91ee977 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -63,6 +63,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.test.mock.MockContext;
import java.io.File;
@@ -195,6 +196,8 @@
return mCountryDetector;
case Context.ROLE_SERVICE:
return mRoleManager;
+ case Context.TELEPHONY_REGISTRY_SERVICE:
+ return mTelephonyRegistryManager;
default:
return null;
}
@@ -214,6 +217,8 @@
return Context.CARRIER_CONFIG_SERVICE;
} else if (svcClass == SubscriptionManager.class) {
return Context.TELEPHONY_SUBSCRIPTION_SERVICE;
+ } else if (svcClass == TelephonyRegistryManager.class) {
+ return Context.TELEPHONY_REGISTRY_SERVICE;
}
throw new UnsupportedOperationException();
}
@@ -463,6 +468,8 @@
private final Configuration mResourceConfiguration = new Configuration();
private final ApplicationInfo mTestApplicationInfo = new ApplicationInfo();
private final RoleManager mRoleManager = mock(RoleManager.class);
+ private final TelephonyRegistryManager mTelephonyRegistryManager =
+ mock(TelephonyRegistryManager.class);
private TelecomManager mTelecomManager = mock(TelecomManager.class);
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index cfc530d..a3b102f 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -62,6 +62,8 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
+import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.text.TextUtils;
import com.android.internal.telecom.IInCallAdapter;
@@ -1022,6 +1024,16 @@
if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ if ((mInCallServiceFixtureX.getCall(ids.mCallId).getProperties() &
+ Call.Details.PROPERTY_IS_EXTERNAL_CALL) == 0) {
+ // Test the PhoneStateBroadcaster functionality if the call is not external.
+ verify(mContext.getSystemService(TelephonyRegistryManager.class),
+ timeout(TEST_TIMEOUT).atLeastOnce())
+ .notifyCallStateChangedForAllSubscriptions(
+ eq(TelephonyManager.CALL_STATE_OFFHOOK),
+ nullable(String.class));
+ }
}
return ids;
}
@@ -1070,6 +1082,16 @@
if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+ if ((mInCallServiceFixtureX.getCall(ids.mCallId).getProperties() &
+ Call.Details.PROPERTY_IS_EXTERNAL_CALL) == 0) {
+ // Test the PhoneStateBroadcaster functionality if the call is not external.
+ verify(mContext.getSystemService(TelephonyRegistryManager.class),
+ timeout(TEST_TIMEOUT).atLeastOnce())
+ .notifyCallStateChangedForAllSubscriptions(
+ eq(TelephonyManager.CALL_STATE_OFFHOOK),
+ nullable(String.class));
+ }
}
return ids;
}