Handle unknown connection from technology swap
If an unknown connection is seen from the Telephony layer, attempt to
use it to replace a matching, existing connection, since that
situation may occur when the underlying technology changes in the
radio layer.
Bug: 19363089
Change-Id: Ibe5b89cc791c2d7e8dfac91c47636361796d68cd
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index 75f472b..cbcf8bb 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -25,8 +25,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.os.UserHandle;
-import android.telecom.CallState;
import android.telecom.PhoneAccount;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
@@ -212,15 +210,21 @@
}
private void addNewUnknownCall(Connection connection) {
- Bundle extras = null;
- if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED &&
- !TextUtils.isEmpty(connection.getAddress())) {
- extras = new Bundle();
- Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
- extras.putParcelable(TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE, uri);
+ Log.i(this, "addNewUnknownCall, connection is: %s", connection);
+ if (!maybeSwapAnyWithUnknownConnection(connection)) {
+ Log.i(this, "determined new connection is: %s", connection);
+ Bundle extras = null;
+ if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED &&
+ !TextUtils.isEmpty(connection.getAddress())) {
+ extras = new Bundle();
+ Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
+ extras.putParcelable(TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE, uri);
+ }
+ TelecomManager.from(mPhoneProxy.getContext()).addNewUnknownCall(
+ PhoneUtils.makePstnPhoneAccountHandle(mPhoneProxy), extras);
+ } else {
+ Log.i(this, "swapped an old connection, new one is: %s", connection);
}
- TelecomManager.from(mPhoneProxy.getContext()).addNewUnknownCall(
- PhoneUtils.makePstnPhoneAccountHandle(mPhoneProxy), extras);
}
/**
@@ -237,4 +241,45 @@
TelecomManager.from(mPhoneProxy.getContext()).addNewIncomingCall(
PhoneUtils.makePstnPhoneAccountHandle(mPhoneProxy), extras);
}
+
+ /**
+ * Define cait.Connection := com.android.internal.telephony.Connection
+ *
+ * Given a previously unknown cait.Connection, check to see if it's likely a replacement for
+ * another cait.Connnection we already know about. If it is, then we silently swap it out
+ * underneath within the relevant {@link TelephonyConnection}, using
+ * {@link TelephonyConnection#setOriginalConnection(Connection)}, and return {@code true}.
+ * Otherwise, we return {@code false}.
+ */
+ private boolean maybeSwapAnyWithUnknownConnection(Connection unknown) {
+ if (!unknown.isIncoming()) {
+ TelecomAccountRegistry registry = TelecomAccountRegistry.getInstance(null);
+ if (registry != null) {
+ TelephonyConnectionService service = registry.getTelephonyConnectionService();
+ if (service != null) {
+ for (android.telecom.Connection telephonyConnection : service
+ .getAllConnections()) {
+ if (maybeSwapWithUnknownConnection(
+ (TelephonyConnection) telephonyConnection,
+ unknown)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean maybeSwapWithUnknownConnection(
+ TelephonyConnection telephonyConnection,
+ Connection unknown) {
+ Connection original = telephonyConnection.getOriginalConnection();
+ if (original != null && !original.isIncoming()
+ && Objects.equals(original.getAddress(), unknown.getAddress())) {
+ telephonyConnection.setOriginalConnection(unknown);
+ return true;
+ }
+ return false;
+ }
}
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 6a533ef..1cb6442 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -204,6 +204,10 @@
private List<AccountEntry> mAccounts = new LinkedList<AccountEntry>();
private int mServiceState = ServiceState.STATE_POWER_OFF;
+ // TODO: Remove back-pointer from app singleton to Service, since this is not a preferred
+ // pattern; redesign. This was added to fix a late release bug.
+ private TelephonyConnectionService mTelephonyConnectionService;
+
TelecomAccountRegistry(Context context) {
mContext = context;
mTelecomManager = TelecomManager.from(context);
@@ -212,12 +216,20 @@
}
static synchronized final TelecomAccountRegistry getInstance(Context context) {
- if (sInstance == null) {
+ if (sInstance == null && context != null) {
sInstance = new TelecomAccountRegistry(context);
}
return sInstance;
}
+ void setTelephonyConnectionService(TelephonyConnectionService telephonyConnectionService) {
+ this.mTelephonyConnectionService = telephonyConnectionService;
+ }
+
+ TelephonyConnectionService getTelephonyConnectionService() {
+ return mTelephonyConnectionService;
+ }
+
/**
* Sets up all the phone accounts for SIMs on first boot.
*/
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 1a2ef53..57f40e9 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -22,7 +22,6 @@
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.ConnectionService;
-import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneNumberUtils;
@@ -74,6 +73,7 @@
super.onCreate();
mExpectedComponentName = new ComponentName(this, this.getClass());
mEmergencyTonePlayer = new EmergencyTonePlayer(this);
+ TelecomAccountRegistry.getInstance(this).setTelephonyConnectionService(this);
}
@Override