diff --git a/api/current.txt b/api/current.txt index 9513d900348eb..195959224ed35 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28092,6 +28092,7 @@ package android.telecom { method public final java.util.List getConferenceableConnections(); method public final java.util.List getConnections(); method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle(); + method public android.telecom.Connection getPrimaryConnection(); method public final int getState(); method public void onAudioStateChanged(android.telecom.AudioState); method public void onDisconnect(); @@ -28181,6 +28182,7 @@ package android.telecom { public abstract class ConnectionService extends android.app.Service { ctor public ConnectionService(); method public final void addConference(android.telecom.Conference); + method public final void addExistingConnection(android.telecom.PhoneAccountHandle, android.telecom.Connection); method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection); method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); @@ -28190,6 +28192,7 @@ package android.telecom { method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onRemoteConferenceAdded(android.telecom.RemoteConference); + method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection); field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService"; } diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index 15cb786fba1ce..003d5cd4876c4 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -333,6 +333,19 @@ public abstract class Conference { return this; } + /** + * Retrieves the primary connection associated with the conference. The primary connection is + * the connection from which the conference will retrieve its current state. + * + * @return The primary connection. + */ + public Connection getPrimaryConnection() { + if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) { + return null; + } + return mUnmodifiableChildConnections.get(0); + } + /** * Inform this Conference that the state of its audio output has been changed externally. * diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 649533e66a79c..6e41c33b7b6f3 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -821,6 +821,40 @@ public abstract class ConnectionService extends Service { } } + /** + * Adds a connection created by the {@link ConnectionService} and informs telecom of the new + * connection. + * + * @param phoneAccountHandle The phone account handle for the connection. + * @param connection The connection to add. + */ + public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle, + Connection connection) { + + String id = addExistingConnectionInternal(connection); + if (id != null) { + List emptyList = new ArrayList<>(0); + + ParcelableConnection parcelableConnection = new ParcelableConnection( + phoneAccountHandle, + connection.getState(), + connection.getCallCapabilities(), + connection.getAddress(), + connection.getAddressPresentation(), + connection.getCallerDisplayName(), + connection.getCallerDisplayNamePresentation(), + connection.getVideoProvider() == null ? + null : connection.getVideoProvider().getInterface(), + connection.getVideoState(), + connection.isRingbackRequested(), + connection.getAudioModeIsVoip(), + connection.getStatusHints(), + connection.getDisconnectCause(), + emptyList); + mAdapter.addExistingConnection(id, parcelableConnection); + } + } + /** * Returns all the active {@code Connection}s for which this {@code ConnectionService} * has taken responsibility. @@ -905,6 +939,12 @@ public abstract class ConnectionService extends Service { public void onRemoteConferenceAdded(RemoteConference conference) {} + /** + * Called when an existing connection is added remotely. + * @param connection The existing connection which was added. + */ + public void onRemoteExistingConnectionAdded(RemoteConnection connection) {} + /** * @hide */ @@ -917,6 +957,11 @@ public abstract class ConnectionService extends Service { onRemoteConferenceAdded(remoteConference); } + /** {@hide} */ + void addRemoteExistingConnection(RemoteConnection remoteConnection) { + onRemoteExistingConnectionAdded(remoteConnection); + } + private void onAccountsInitialized() { mAreAccountsInitialized = true; for (Runnable r : mPreInitializationConnectionRequests) { @@ -925,6 +970,18 @@ public abstract class ConnectionService extends Service { mPreInitializationConnectionRequests.clear(); } + /** + * Adds an existing connection to the list of connections, identified by a new UUID. + * + * @param connection The connection. + * @return The UUID of the connection (e.g. the call-id). + */ + private String addExistingConnectionInternal(Connection connection) { + String id = UUID.randomUUID().toString(); + addConnection(id, connection); + return id; + } + private void addConnection(String callId, Connection connection) { mConnectionById.put(callId, connection); mIdByConnection.put(connection, callId); diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index c67617241f506..e67af8cf906d8 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -344,4 +344,20 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } } + + /** + * Informs telecom of an existing connection which was added by the {@link ConnectionService}. + * + * @param callId The unique ID of the call being added. + * @param connection The connection. + */ + void addExistingConnection(String callId, ParcelableConnection connection) { + Log.v(this, "addExistingConnection: %s", callId); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.addExistingConnection(callId, connection); + } catch (RemoteException ignored) { + } + } + } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index 217dbc3ac6f41..519a400f6447c 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -57,6 +57,7 @@ final class ConnectionServiceAdapterServant { private static final int MSG_SET_ADDRESS = 18; private static final int MSG_SET_CALLER_DISPLAY_NAME = 19; private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20; + private static final int MSG_ADD_EXISTING_CONNECTION = 21; private final IConnectionServiceAdapter mDelegate; @@ -199,6 +200,16 @@ final class ConnectionServiceAdapterServant { } break; } + case MSG_ADD_EXISTING_CONNECTION: { + SomeArgs args = (SomeArgs) msg.obj; + try { + mDelegate.addExistingConnection( + (String) args.arg1, (ParcelableConnection) args.arg2); + } finally { + args.recycle(); + } + break; + } } } }; @@ -345,6 +356,15 @@ final class ConnectionServiceAdapterServant { args.arg2 = conferenceableConnectionIds; mHandler.obtainMessage(MSG_SET_CONFERENCEABLE_CONNECTIONS, args).sendToTarget(); } + + @Override + public final void addExistingConnection( + String connectionId, ParcelableConnection connection) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = connectionId; + args.arg2 = connection; + mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget(); + } }; public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) { diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 9a094df0376dd..816e2bf6b4189 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -406,6 +406,29 @@ public final class RemoteConnection { mState = Connection.STATE_INITIALIZING; } + /** + * @hide + */ + RemoteConnection(String callId, IConnectionService connectionService, + ParcelableConnection connection) { + mConnectionId = callId; + mConnectionService = connectionService; + mConnected = true; + mState = connection.getState(); + mDisconnectCause = connection.getDisconnectCause(); + mRingbackRequested = connection.isRingbackRequested(); + mCallCapabilities = connection.getCapabilities(); + mVideoState = connection.getVideoState(); + mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider()); + mIsVoipAudioMode = connection.getIsVoipAudioMode(); + mStatusHints = connection.getStatusHints(); + mAddress = connection.getHandle(); + mAddressPresentation = connection.getHandlePresentation(); + mCallerDisplayName = connection.getCallerDisplayName(); + mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation(); + mConference = null; + } + /** * Create a RemoteConnection which is used for failed connections. Note that using it for any * "real" purpose will almost certainly fail. Callers should note the failure and act @@ -415,7 +438,7 @@ public final class RemoteConnection { * @hide */ RemoteConnection(DisconnectCause disconnectCause) { - this("NULL", null, null); + mConnectionId = "NULL"; mConnected = false; mState = Connection.STATE_DISCONNECTED; mDisconnectCause = disconnectCause; diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index af4ee22ef2af3..4bb78c0103034 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -41,8 +41,9 @@ import java.util.UUID; */ final class RemoteConnectionService { + // Note: Casting null to avoid ambiguous constructor reference. private static final RemoteConnection NULL_CONNECTION = - new RemoteConnection("NULL", null, null); + new RemoteConnection("NULL", null, (ConnectionRequest) null); private static final RemoteConference NULL_CONFERENCE = new RemoteConference("NULL", null); @@ -286,6 +287,15 @@ final class RemoteConnectionService { .setConferenceableConnections(conferenceable); } } + + @Override + public void addExistingConnection(String callId, ParcelableConnection connection) { + // TODO: add contents of this method + RemoteConnection remoteConnction = new RemoteConnection(callId, + mOutgoingConnectionServiceRpc, connection); + + mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnction); + } }; private final ConnectionServiceAdapterServant mServant = diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index 5daa568bffc50..0d6b3d9bbb124 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -77,4 +77,6 @@ oneway interface IConnectionServiceAdapter { void setCallerDisplayName(String callId, String callerDisplayName, int presentation); void setConferenceableConnections(String callId, in List conferenceableCallIds); + + void addExistingConnection(String callId, in ParcelableConnection connection); }