Cleanup Telecom API usage in Telephony for mainline support.
1. Moved some Connection#Listener callbacks to TelephonyConnection; these
were Telephony implementation details that leaked into the telecom API
class (example: conference participants stuff is IMS specific).
2. Use public Connection#putExtras API instead of using @hide putters on
the Connection class.
3. Cleanup code which used @hide Connection#getConnectionService to get
the current ConnectionService and track this in TelephonyConnection
instead.
4. Inline uses of Connection#can; its just simple bit math.
5. Fix break in TelephonyConnectionServiceTest related to emergency number
tracker (unrelated to this refactor but I was running the tests so might
as well fix it).
Test: Smoke test.
Test: Run unit tests
Test: Run CTS tests.
Change-Id: I83043caa19cdfb990f47e6b124c12e569a86e692
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index e14f422..1969b10 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -110,6 +110,25 @@
handleOriginalConnectionChange();
}
}
+
+ /**
+ * Handles changes to conference participant data as reported by the conference host
+ * connection.
+ *
+ * @param c The connection.
+ * @param participants The participant information.
+ */
+ @Override
+ public void onConferenceParticipantsChanged(android.telecom.Connection c,
+ List<ConferenceParticipant> participants) {
+
+ if (c == null || participants == null) {
+ return;
+ }
+ Log.v(this, "onConferenceParticipantsChanged: %d participants", participants.size());
+ TelephonyConnection telephonyConnection = (TelephonyConnection) c;
+ handleConferenceParticipantsUpdate(telephonyConnection, participants);
+ }
};
/**
@@ -140,25 +159,6 @@
setDisconnected(disconnectCause);
}
- /**
- * Handles changes to conference participant data as reported by the conference host
- * connection.
- *
- * @param c The connection.
- * @param participants The participant information.
- */
- @Override
- public void onConferenceParticipantsChanged(android.telecom.Connection c,
- List<ConferenceParticipant> participants) {
-
- if (c == null || participants == null) {
- return;
- }
- Log.v(this, "onConferenceParticipantsChanged: %d participants", participants.size());
- TelephonyConnection telephonyConnection = (TelephonyConnection) c;
- handleConferenceParticipantsUpdate(telephonyConnection, participants);
- }
-
@Override
public void onVideoStateChanged(android.telecom.Connection c, int videoState) {
Log.d(this, "onVideoStateChanged video state %d", videoState);
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 9902700..b193c7f 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -53,6 +53,21 @@
}
};
+ private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
+ new TelephonyConnection.TelephonyConnectionListener() {
+ @Override
+ public void onConferenceStarted() {
+ Log.v(this, "onConferenceStarted");
+ recalculate();
+ }
+
+ @Override
+ public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {
+ Log.v(this, "onConferenceSupportedChanged");
+ recalculate();
+ }
+ };
+
/**
* Ims conference controller connection listener. Used to respond to changes in state of the
* Telephony connections the controller is aware of.
@@ -74,18 +89,6 @@
public void onDestroyed(Connection connection) {
remove(connection);
}
-
- @Override
- public void onConferenceStarted() {
- Log.v(this, "onConferenceStarted");
- recalculate();
- }
-
- @Override
- public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {
- Log.v(this, "onConferenceSupportedChanged");
- recalculate();
- }
};
/**
@@ -149,6 +152,7 @@
mTelephonyConnections.add(connection);
connection.addConnectionListener(mConnectionListener);
+ connection.addTelephonyConnectionListener(mTelephonyConnectionListener);
recalculateConference();
}
@@ -176,6 +180,10 @@
}
connection.removeConnectionListener(mConnectionListener);
+ if (connection instanceof TelephonyConnection) {
+ TelephonyConnection telephonyConnection = (TelephonyConnection) connection;
+ telephonyConnection.removeTelephonyConnectionListener(mTelephonyConnectionListener);
+ }
mTelephonyConnections.remove(connection);
recalculateConferenceable();
}
@@ -388,6 +396,7 @@
// Use the "Other" disconnect cause to ensure the call is logged to the call log but the
// disconnect tone is not played.
connection.removeConnectionListener(mConnectionListener);
+ connection.removeTelephonyConnectionListener(mTelephonyConnectionListener);
connection.clearOriginalConnection();
connection.setDisconnected(new DisconnectCause(DisconnectCause.OTHER,
android.telephony.DisconnectCause.toString(
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 25949d0..b19084d 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -26,8 +26,10 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.telecom.CallAudioState;
+import android.telecom.Conference;
import android.telecom.ConferenceParticipant;
import android.telecom.Connection;
+import android.telecom.ConnectionService;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.StatusHints;
@@ -407,6 +409,10 @@
public abstract static class TelephonyConnectionListener {
public void onOriginalConnectionConfigured(TelephonyConnection c) {}
public void onOriginalConnectionRetry(TelephonyConnection c, boolean isPermanentFailure) {}
+ public void onConferenceParticipantsChanged(Connection c,
+ List<ConferenceParticipant> participants) {}
+ public void onConferenceStarted() {}
+ public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
}
private final PostDialListener mPostDialListener = new PostDialListener() {
@@ -624,6 +630,7 @@
}
};
+ private TelephonyConnectionService mTelephonyConnectionService;
protected com.android.internal.telephony.Connection mOriginalConnection;
private Call.State mConnectionState = Call.State.IDLE;
private Bundle mOriginalConnectionExtras = new Bundle();
@@ -1266,13 +1273,23 @@
*/
private void setTechnologyTypeExtra() {
if (getPhone() != null) {
- putExtra(TelecomManager.EXTRA_CALL_TECHNOLOGY_TYPE, getPhone().getPhoneType());
+ Bundle newExtras = getExtras();
+ if (newExtras == null) {
+ newExtras = new Bundle();
+ }
+ newExtras.putInt(TelecomManager.EXTRA_CALL_TECHNOLOGY_TYPE, getPhone().getPhoneType());
+ putExtras(newExtras);
}
}
private void refreshDisableAddCall() {
if (shouldSetDisableAddCallExtra()) {
- putExtra(Connection.EXTRA_DISABLE_ADD_CALL, true);
+ Bundle newExtras = getExtras();
+ if (newExtras == null) {
+ newExtras = new Bundle();
+ }
+ newExtras.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true);
+ putExtras(newExtras);
} else {
removeExtras(Connection.EXTRA_DISABLE_ADD_CALL);
}
@@ -1760,8 +1777,8 @@
// To "optimize", we check here to see if there already exists any active calls. If so,
// we issue an update for those calls first to make sure we only have one top-level
// active call.
- if (getConnectionService() != null) {
- for (Connection current : getConnectionService().getAllConnections()) {
+ if (getTelephonyConnectionService() != null) {
+ for (Connection current : getTelephonyConnectionService().getAllConnections()) {
if (current != this && current instanceof TelephonyConnection) {
TelephonyConnection other = (TelephonyConnection) current;
if (other.getState() == STATE_ACTIVE) {
@@ -1788,9 +1805,10 @@
* @return {@code true} if the connection is video capable, {@code false} otherwise.
*/
private boolean isVideoCapable() {
- return can(mOriginalConnectionCapabilities, Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
- && can(mOriginalConnectionCapabilities,
- Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
+ return (mOriginalConnectionCapabilities & Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
+ == Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL
+ && (mOriginalConnectionCapabilities & Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL)
+ == Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL;
}
/**
@@ -1802,7 +1820,8 @@
* @return {@code true} if the connection is external, {@code false} otherwise.
*/
private boolean isExternalConnection() {
- return can(mOriginalConnectionCapabilities, Capability.IS_EXTERNAL_CONNECTION);
+ return (mOriginalConnectionCapabilities
+ & Capability.IS_EXTERNAL_CONNECTION) == Capability.IS_EXTERNAL_CONNECTION;
}
/**
@@ -1824,8 +1843,10 @@
* @return {@code true} if the connection is pullable, {@code false} otherwise.
*/
private boolean isPullable() {
- return can(mOriginalConnectionCapabilities, Capability.IS_EXTERNAL_CONNECTION)
- && can(mOriginalConnectionCapabilities, Capability.IS_PULLABLE);
+ return (mOriginalConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION)
+ == Capability.IS_EXTERNAL_CONNECTION
+ && (mOriginalConnectionCapabilities & Capability.IS_PULLABLE)
+ == Capability.IS_PULLABLE;
}
/**
@@ -1883,17 +1904,20 @@
public int applyOriginalConnectionCapabilities(int capabilities) {
// We only support downgrading to audio if both the remote and local side support
// downgrading to audio.
- boolean supportsDowngradeToAudio = can(mOriginalConnectionCapabilities,
- Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL |
- Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE);
+ int supportsDowngrade = Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL
+ | Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE;
+ boolean supportsDowngradeToAudio =
+ (mOriginalConnectionCapabilities & supportsDowngrade) == supportsDowngrade;
capabilities = changeBitmask(capabilities,
CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, !supportsDowngradeToAudio);
capabilities = changeBitmask(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
- can(mOriginalConnectionCapabilities, Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL));
+ (mOriginalConnectionCapabilities & Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL)
+ == Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
- boolean isLocalVideoSupported = can(mOriginalConnectionCapabilities,
- Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL) && !mIsTtyEnabled;
+ boolean isLocalVideoSupported = (mOriginalConnectionCapabilities
+ & Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
+ == Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL && !mIsTtyEnabled;
capabilities = changeBitmask(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
isLocalVideoSupported);
@@ -2344,4 +2368,47 @@
sb.append("]");
return sb.toString();
}
+
+ public final void setTelephonyConnectionService(TelephonyConnectionService connectionService) {
+ mTelephonyConnectionService = connectionService;
+ }
+
+ public final TelephonyConnectionService getTelephonyConnectionService() {
+ return mTelephonyConnectionService;
+ }
+
+ /**
+ * Notifies listeners of a change to conference participant(s).
+ *
+ * @param conferenceParticipants The participants.
+ */
+ protected final void updateConferenceParticipants(
+ List<ConferenceParticipant> conferenceParticipants) {
+ for (TelephonyConnectionListener l : mTelephonyListeners) {
+ l.onConferenceParticipantsChanged(this, conferenceParticipants);
+ }
+ }
+
+ /**
+ * Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()}
+ * operation has started.
+ * <p>
+ */
+ protected void notifyConferenceStarted() {
+ for (TelephonyConnectionListener l : mTelephonyListeners) {
+ l.onConferenceStarted();
+ }
+ }
+
+ /**
+ * Notifies listeners when a change has occurred to the Connection which impacts its ability to
+ * be a part of a conference call.
+ * @param isConferenceSupported {@code true} if the connection supports being part of a
+ * conference call, {@code false} otherwise.
+ */
+ protected void notifyConferenceSupportedChanged(boolean isConferenceSupported) {
+ for (TelephonyConnectionListener l : mTelephonyListeners) {
+ l.onConferenceSupportedChanged(this, isConferenceSupported);
+ }
+ }
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 0e5a612..5e3a899 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1344,6 +1344,7 @@
returnConnection.setShowPreciseFailedCause(
TelecomAccountRegistry.getInstance(this).isShowPreciseFailedCause(
phoneAccountHandle));
+ returnConnection.setTelephonyConnectionService(this);
}
return returnConnection;
}
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 1329a77..ab4c067 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -46,6 +46,7 @@
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import org.junit.After;
@@ -72,6 +73,7 @@
@Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
@Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy;
@Mock TelephonyConnectionService.PhoneFactoryProxy mPhoneFactoryProxy;
+ @Mock EmergencyNumberTracker mEmergencyNumberTracker;
TelephonyConnectionService mTestConnectionService;
@@ -818,6 +820,8 @@
when(phone.getServiceState()).thenReturn(testServiceState);
when(phone.getPhoneId()).thenReturn(phoneId);
when(phone.getDefaultPhone()).thenReturn(phone);
+ when(phone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker);
+ when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null);
return phone;
}
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index b6e4bf3..f77fd30 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -31,6 +32,7 @@
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -56,6 +58,9 @@
@Mock
Resources mMockResources;
+ @Mock
+ EmergencyNumberTracker mEmergencyNumberTracker;
+
private Phone mMockPhone;
private int mNotifyPhoneAccountChangedCount = 0;
private List<String> mLastConnectionEvents = new ArrayList<>();
@@ -80,6 +85,8 @@
doNothing().when(mMockRadioConnection).addListener(any(Connection.Listener.class));
doNothing().when(mMockRadioConnection).addPostDialListener(
any(Connection.PostDialListener.class));
+ when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null);
+ when(mMockPhone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker);
when(mMockPhone.getRingingCall()).thenReturn(mMockCall);
when(mMockPhone.getContext()).thenReturn(mMockContext);
when(mMockPhone.getCurrentSubscriberUris()).thenReturn(null);