diff --git a/api/current.txt b/api/current.txt index d482260e38076..22d1b64fa7584 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28586,7 +28586,11 @@ package android.telecomm { method public final int getCallCapabilities(); method public final java.lang.String getCallerDisplayName(); method public final int getCallerDisplayNamePresentation(); + method public static android.telecomm.Connection getCanceledConnection(); method public final java.util.List getChildConnections(); + method public static android.telecomm.Connection getFailedConnection(int, java.lang.String); + method public final int getFailureCode(); + method public final java.lang.String getFailureMessage(); method public final android.net.Uri getHandle(); method public final int getHandlePresentation(); method public final android.telecomm.Connection getParentConnection(); @@ -28615,9 +28619,13 @@ package android.telecomm { method public final void setAudioModeIsVoip(boolean); method public final void setCallCapabilities(int); method public final void setCallerDisplayName(java.lang.String, int); + method public final void setCanceled(); method public final void setDialing(); method public final void setDisconnected(int, java.lang.String); + method public final void setFailed(int, java.lang.String); method public final void setHandle(android.net.Uri, int); + method public final void setInitialized(); + method public final void setInitializing(); method public final void setOnHold(); method public final void setParentConnection(android.telecomm.Connection); method public final void setPostDialWait(java.lang.String); @@ -28632,12 +28640,15 @@ package android.telecomm { } public final class Connection.State { - field public static final int ACTIVE = 3; // 0x3 - field public static final int DIALING = 2; // 0x2 - field public static final int DISCONNECTED = 5; // 0x5 - field public static final int HOLDING = 4; // 0x4 - field public static final int NEW = 0; // 0x0 - field public static final int RINGING = 1; // 0x1 + field public static final int ACTIVE = 4; // 0x4 + field public static final int CANCELED = 8; // 0x8 + field public static final int DIALING = 3; // 0x3 + field public static final int DISCONNECTED = 6; // 0x6 + field public static final int FAILED = 7; // 0x7 + field public static final int HOLDING = 5; // 0x5 + field public static final int INITIALIZING = 0; // 0x0 + field public static final int NEW = 1; // 0x1 + field public static final int RINGING = 2; // 0x2 } public final class ConnectionRequest implements android.os.Parcelable { @@ -28655,17 +28666,16 @@ package android.telecomm { public abstract class ConnectionService extends android.app.Service { ctor public ConnectionService(); - method public final void createRemoteIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse); - method public final void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse); + method public final android.telecomm.RemoteConnection createRemoteIncomingConnection(android.telecomm.ConnectionRequest); + method public final android.telecomm.RemoteConnection createRemoteOutgoingConnection(android.telecomm.ConnectionRequest); method public final java.util.Collection getAllConnections(); - method public final void lookupRemoteAccounts(android.net.Uri, android.telecomm.SimpleResponse>); method public final void maybeRespondToAccountLookup(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnectionAdded(android.telecomm.Connection); method public void onConnectionRemoved(android.telecomm.Connection); method public void onCreateConferenceConnection(java.lang.String, android.telecomm.Connection, android.telecomm.Response); - method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse); - method public void onCreateOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse); + method public android.telecomm.Connection onCreateIncomingConnection(android.telecomm.ConnectionRequest); + method public android.telecomm.Connection onCreateOutgoingConnection(android.telecomm.ConnectionRequest); field public static final java.lang.String SERVICE_INTERFACE = "android.telecomm.ConnectionService"; } @@ -28796,6 +28806,8 @@ package android.telecomm { method public int getCallerDisplayNamePresentation(); method public int getDisconnectCause(); method public java.lang.String getDisconnectMessage(); + method public int getFailureCode(); + method public java.lang.String getFailureMessage(); method public android.net.Uri getHandle(); method public int getHandlePresentation(); method public int getState(); @@ -28812,19 +28824,20 @@ package android.telecomm { method public void unhold(); } - public static abstract interface RemoteConnection.Listener { - method public abstract void onAudioModeIsVoipChanged(android.telecomm.RemoteConnection, boolean); - method public abstract void onCallCapabilitiesChanged(android.telecomm.RemoteConnection, int); - method public abstract void onCallerDisplayNameChanged(android.telecomm.RemoteConnection, java.lang.String, int); - method public abstract void onDestroyed(android.telecomm.RemoteConnection); - method public abstract void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String); - method public abstract void onHandleChanged(android.telecomm.RemoteConnection, android.net.Uri, int); - method public abstract void onPostDialWait(android.telecomm.RemoteConnection, java.lang.String); - method public abstract void onRequestingRingback(android.telecomm.RemoteConnection, boolean); - method public abstract void onStartActivityFromInCall(android.telecomm.RemoteConnection, android.app.PendingIntent); - method public abstract void onStateChanged(android.telecomm.RemoteConnection, int); - method public abstract void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints); - method public abstract void onVideoStateChanged(android.telecomm.RemoteConnection, int); + public static abstract class RemoteConnection.Listener { + ctor public RemoteConnection.Listener(); + method public void onAudioModeIsVoipChanged(android.telecomm.RemoteConnection, boolean); + method public void onCallCapabilitiesChanged(android.telecomm.RemoteConnection, int); + method public void onCallerDisplayNameChanged(android.telecomm.RemoteConnection, java.lang.String, int); + method public void onDestroyed(android.telecomm.RemoteConnection); + method public void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String); + method public void onHandleChanged(android.telecomm.RemoteConnection, android.net.Uri, int); + method public void onPostDialWait(android.telecomm.RemoteConnection, java.lang.String); + method public void onRequestingRingback(android.telecomm.RemoteConnection, boolean); + method public void onStartActivityFromInCall(android.telecomm.RemoteConnection, android.app.PendingIntent); + method public void onStateChanged(android.telecomm.RemoteConnection, int); + method public void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints); + method public void onVideoStateChanged(android.telecomm.RemoteConnection, int); } public abstract interface Response { diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java index 98b82495e463b..6043232bcfd71 100644 --- a/telecomm/java/android/telecomm/Connection.java +++ b/telecomm/java/android/telecomm/Connection.java @@ -48,17 +48,22 @@ public abstract class Connection { public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {} public void onStatusHintsChanged(Connection c, StatusHints statusHints) {} public void onStartActivityFromInCall(Connection c, PendingIntent intent) {} + public void onFailed(Connection c, int code, String msg) {} } public final class State { private State() {} - public static final int NEW = 0; - public static final int RINGING = 1; - public static final int DIALING = 2; - public static final int ACTIVE = 3; - public static final int HOLDING = 4; - public static final int DISCONNECTED = 5; + public static final int INITIALIZING = 0; + public static final int NEW = 1; + public static final int RINGING = 2; + public static final int DIALING = 3; + public static final int ACTIVE = 4; + public static final int HOLDING = 5; + public static final int DISCONNECTED = 6; + public static final int FAILED = 7; + public static final int CANCELED = 8; + } private final Set mListeners = new HashSet<>(); @@ -77,6 +82,9 @@ public abstract class Connection { private boolean mAudioModeIsVoip; private StatusHints mStatusHints; private int mVideoState; + private int mFailureCode; + private String mFailureMessage; + private boolean mIsCanceled; /** * Create a new Connection. @@ -196,6 +204,20 @@ public abstract class Connection { return this; } + /** + * @return The failure code ({@see DisconnectCause}) associated with this failed connection. + */ + public final int getFailureCode() { + return mFailureCode; + } + + /** + * @return The reason for the connection failure. This will not be displayed to the user. + */ + public final String getFailureMessage() { + return mFailureMessage; + } + /** * Inform this Connection that the state of its audio output has been changed externally. * @@ -226,6 +248,10 @@ public abstract class Connection { return "HOLDING"; case State.DISCONNECTED: return "DISCONNECTED"; + case State.FAILED: + return "FAILED"; + case State.CANCELED: + return "CANCELED"; default: Log.wtf(Connection.class, "Unknown state %d", state); return "UNKNOWN"; @@ -299,6 +325,33 @@ public abstract class Connection { } } + /** + * Cancel the {@link Connection}. Once this is called, the {@link Connection} will not be used, + * and no subsequent {@link Connection}s will be attempted. + */ + public final void setCanceled() { + Log.d(this, "setCanceled"); + setState(State.CANCELED); + } + + /** + * Move the {@link Connection} to the {@link State#FAILED} state, with the given code + * ({@see DisconnectCause}) and message. This message is not shown to the user, but is useful + * for logging and debugging purposes. + *

+ * After calling this, the {@link Connection} will not be used. + * + * @param code The {@link android.telephony.DisconnectCause} indicating why the connection + * failed. + * @param message A message explaining why the {@link Connection} failed. + */ + public final void setFailed(int code, String message) { + Log.d(this, "setFailed (%d: %s)", code, message); + mFailureCode = code; + mFailureMessage = message; + setState(State.FAILED); + } + /** * Set the video state for the connection. * Valid values: {@link android.telecomm.VideoCallProfile#VIDEO_STATE_AUDIO_ONLY}, @@ -332,6 +385,20 @@ public abstract class Connection { setState(State.RINGING); } + /** + * Sets state to initializing (this Connection is not yet ready to be used). + */ + public final void setInitializing() { + setState(State.INITIALIZING); + } + + /** + * Sets state to initialized (the Connection has been set up and is now ready to be used). + */ + public final void setInitialized() { + setState(State.NEW); + } + /** * Sets state to dialing (e.g., dialing an outbound call). */ @@ -485,8 +552,8 @@ public abstract class Connection { public void onSetAudioState(CallAudioState state) {} /** - * Notifies this Connection of an internal state change. This method is called before the - * state is actually changed. + * Notifies this Connection of an internal state change. This method is called after the + * state is changed. * * @param state The new state, a {@link Connection.State} member. */ @@ -577,11 +644,50 @@ public abstract class Connection { } private void setState(int state) { - Log.d(this, "setState: %s", stateToString(state)); - this.mState = state; - for (Listener l : mListeners) { - l.onStateChanged(this, state); + if (mState == State.FAILED || mState == State.CANCELED) { + Log.d(this, "Connection already %s; cannot transition out of this state.", + stateToString(mState)); + return; } - onSetState(state); + if (mState != state) { + Log.d(this, "setState: %s", stateToString(state)); + mState = state; + for (Listener l : mListeners) { + l.onStateChanged(this, state); + } + onSetState(state); + } + } + + /** + * Return a {@link Connection} which represents a failed connection attempt. The returned + * {@link Connection} will have {@link #getFailureCode()}, {@link #getFailureMessage()}, and + * {@link #getState()} set appropriately, but the {@link Connection} itself should not be used + * for anything. + * + * @param code The failure code ({@see DisconnectCause}). + * @param message A reason for why the connection failed (not intended to be shown to the user). + * @return A {@link Connection} which indicates failure. + */ + public static Connection getFailedConnection(final int code, final String message) { + return new Connection() {{ + setFailed(code, message); + }}; + } + + private static final Connection CANCELED_CONNECTION = new Connection() {{ + setCanceled(); + }}; + + /** + * Return a {@link Connection} which represents a canceled a connection attempt. The returned + * {@link Connection} will have state {@link State#CANCELED}, and cannot be moved out of that + * state. This connection should not be used for anything, and no other {@link Connection}s + * should be attempted. + * + * @return A {@link Connection} which indicates that the underlying call should be canceled. + */ + public static Connection getCanceledConnection() { + return CANCELED_CONNECTION; } } diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java index 4d945a31f98ae..020b692b8d59f 100644 --- a/telecomm/java/android/telecomm/ConnectionRequest.java +++ b/telecomm/java/android/telecomm/ConnectionRequest.java @@ -20,6 +20,8 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.os.ResultReceiver; +import android.telephony.DisconnectCause; /** * Simple data container encapsulating a request to some entity to @@ -110,6 +112,7 @@ public final class ConnectionRequest implements Parcelable { return mVideoState; } + @Override public String toString() { return String.format("PhoneConnectionRequest %s %s", mHandle == null diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java index 19e44890daa29..51876df068b59 100644 --- a/telecomm/java/android/telecomm/ConnectionService.java +++ b/telecomm/java/android/telecomm/ConnectionService.java @@ -28,7 +28,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; - +import android.telephony.DisconnectCause; import com.android.internal.os.SomeArgs; import com.android.internal.telecomm.IConnectionService; import com.android.internal.telecomm.IConnectionServiceAdapter; @@ -132,7 +132,7 @@ public abstract class ConnectionService extends Service { public void answer(String callId, int videoState) { SomeArgs args = SomeArgs.obtain(); args.arg1 = callId; - args.arg2 = videoState; + args.argi1 = videoState; mHandler.obtainMessage(MSG_ANSWER, args).sendToTarget(); } @@ -224,7 +224,7 @@ public abstract class ConnectionService extends Service { SomeArgs args = (SomeArgs) msg.obj; try { String callId = (String) args.arg1; - int videoState = (int) args.arg2; + int videoState = args.argi1; answer(callId, videoState); } finally { args.recycle(); @@ -425,48 +425,76 @@ public abstract class ConnectionService extends Service { * incoming call. In either case, telecomm will cycle through a set of services and call * createConnection util a connection service cancels the process or completes it successfully. */ - private void createConnection(ConnectionRequest originalRequest, boolean isIncoming) { - Log.d(this, "call %s", originalRequest); - CreateConnectionResponse response = new CreateConnectionResponse() { - @Override - public void onSuccess(ConnectionRequest request, Connection connection) { - Log.d(this, "adapter handleCreateConnectionSuccessful %s", - request.getCallId()); - addConnection(request.getCallId(), connection); - mAdapter.handleCreateConnectionSuccessful( - request, - new ParcelableConnection( - request.getAccountHandle(), - connection.getState(), - connection.getCallCapabilities(), - connection.getHandle(), - connection.getHandlePresentation(), - connection.getCallerDisplayName(), - connection.getCallerDisplayNamePresentation(), - connection.getVideoCallProvider() == null ? - null : connection.getVideoCallProvider().getInterface(), - connection.getVideoState())); - } + private void createConnection(final ConnectionRequest request, boolean isIncoming) { + Log.d(this, "call %s", request); - @Override - public void onFailure(ConnectionRequest request, int code, String msg) { - // Tell telecomm to try a different service. - mAdapter.handleCreateConnectionFailed(request, code, msg); - } + final Connection createdConnection; + if (isIncoming) { + createdConnection = onCreateIncomingConnection(request); + } else { + createdConnection = onCreateOutgoingConnection(request); + } - @Override - public void onCancel(ConnectionRequest request) { + if (createdConnection != null) { + Log.d(this, "adapter handleCreateConnectionSuccessful %s", + request.getCallId()); + if (createdConnection.getState() == Connection.State.INITIALIZING) { + // Wait for the connection to become initialized. + createdConnection.addConnectionListener(new Connection.Listener() { + @Override + public void onStateChanged(Connection c, int state) { + switch (state) { + case Connection.State.FAILED: + Log.d(this, "Connection (%s) failed (%d: %s)", request, + c.getFailureCode(), c.getFailureMessage()); + mAdapter.handleCreateConnectionFailed(request, c.getFailureCode(), + c.getFailureMessage()); + break; + case Connection.State.CANCELED: + Log.d(this, "Connection (%s) canceled", request); + mAdapter.handleCreateConnectionCancelled(request); + break; + case Connection.State.INITIALIZING: + Log.d(this, "State changed to INITIALIZING; ignoring"); + return; // Don't want to stop listening on this state transition. + default: + Log.d(this, "Connection created in state %s", + Connection.stateToString(state)); + connectionCreated(request, createdConnection); + break; + } + c.removeConnectionListener(this); + } + }); + } else if (createdConnection.getState() == Connection.State.CANCELED) { // Tell telecomm not to attempt any more services. mAdapter.handleCreateConnectionCancelled(request); + } else { + connectionCreated(request, createdConnection); } - }; - if (isIncoming) { - onCreateIncomingConnection(originalRequest, response); } else { - onCreateOutgoingConnection(originalRequest, response); + // Tell telecomm to try a different service. + mAdapter.handleCreateConnectionFailed(request, DisconnectCause.ERROR_UNSPECIFIED, null); } } + private void connectionCreated(ConnectionRequest request, Connection connection) { + addConnection(request.getCallId(), connection); + mAdapter.handleCreateConnectionSuccessful( + request, + new ParcelableConnection( + request.getAccountHandle(), + connection.getState(), + connection.getCallCapabilities(), + connection.getHandle(), + connection.getHandlePresentation(), + connection.getCallerDisplayName(), + connection.getCallerDisplayNamePresentation(), + connection.getVideoCallProvider() == null ? + null : connection.getVideoCallProvider().getInterface(), + connection.getVideoState())); + } + private void abort(String callId) { Log.d(this, "abort %s", callId); findConnectionForAction(callId, "abort").onAbort(); @@ -609,13 +637,6 @@ public abstract class ConnectionService extends Service { }); } - public final void lookupRemoteAccounts( - Uri handle, SimpleResponse> response) { - mAccountLookupResponse = response; - mAccountLookupHandle = handle; - maybeRespondToAccountLookup(); - } - public final void maybeRespondToAccountLookup() { if (mAreAccountsInitialized && mAccountLookupResponse != null) { mAccountLookupResponse.onResult( @@ -627,16 +648,12 @@ public abstract class ConnectionService extends Service { } } - public final void createRemoteIncomingConnection( - ConnectionRequest request, - CreateConnectionResponse response) { - mRemoteConnectionManager.createRemoteConnection(request, response, true); + public final RemoteConnection createRemoteIncomingConnection(ConnectionRequest request) { + return mRemoteConnectionManager.createRemoteConnection(request, true); } - public final void createRemoteOutgoingConnection( - ConnectionRequest request, - CreateConnectionResponse response) { - mRemoteConnectionManager.createRemoteConnection(request, response, false); + public final RemoteConnection createRemoteOutgoingConnection(ConnectionRequest request) { + return mRemoteConnectionManager.createRemoteConnection(request, false); } /** @@ -649,23 +666,22 @@ public abstract class ConnectionService extends Service { /** * Create a Connection given an incoming request. This is used to attach to existing incoming * calls. - * * @param request Details about the incoming call. - * @param callback A callback for providing the result. + * + * @return The {@link Connection} object to satisfy this call, or {@code null} to not handle + * the call. */ - public void onCreateIncomingConnection( - ConnectionRequest request, - CreateConnectionResponse callback) {} + public Connection onCreateIncomingConnection(ConnectionRequest request) { return null; } /** * Create a Connection given an outgoing request. This is used to initiate new outgoing calls. + * @param request Details about the outgoing call. + * + * @return The {@link Connection} object to satisfy this request, + * or null to not handle the call. * - * @param request Details about the outgoing call. - * @param callback A callback for providing the result. */ - public void onCreateOutgoingConnection( - ConnectionRequest request, - CreateConnectionResponse callback) {} + public Connection onCreateOutgoingConnection(ConnectionRequest request) { return null; } /** * Returns a new or existing conference connection when the the user elects to convert the diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java index ddad58f8b12aa..ab980e8259e72 100644 --- a/telecomm/java/android/telecomm/RemoteConnection.java +++ b/telecomm/java/android/telecomm/RemoteConnection.java @@ -18,7 +18,6 @@ package android.telecomm; import android.app.PendingIntent; import android.net.Uri; -import android.os.Bundle; import android.os.RemoteException; import android.telephony.DisconnectCause; @@ -31,23 +30,23 @@ import java.util.Set; * RemoteConnection object used by RemoteConnectionService. */ public final class RemoteConnection { - public interface Listener { - void onStateChanged(RemoteConnection connection, int state); - void onDisconnected(RemoteConnection connection, int cause, String message); - void onRequestingRingback(RemoteConnection connection, boolean ringback); - void onCallCapabilitiesChanged(RemoteConnection connection, int callCapabilities); - void onPostDialWait(RemoteConnection connection, String remainingDigits); - void onAudioModeIsVoipChanged(RemoteConnection connection, boolean isVoip); - void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints); - void onHandleChanged(RemoteConnection connection, Uri handle, int presentation); - void onCallerDisplayNameChanged( - RemoteConnection connection, String callerDisplayName, int presentation); - void onVideoStateChanged(RemoteConnection connection, int videoState); - void onStartActivityFromInCall(RemoteConnection connection, PendingIntent intent); - void onDestroyed(RemoteConnection connection); + public static abstract class Listener { + public void onStateChanged(RemoteConnection connection, int state) {} + public void onDisconnected(RemoteConnection connection, int cause, String message) {} + public void onRequestingRingback(RemoteConnection connection, boolean ringback) {} + public void onCallCapabilitiesChanged(RemoteConnection connection, int callCapabilities) {} + public void onPostDialWait(RemoteConnection connection, String remainingDigits) {} + public void onAudioModeIsVoipChanged(RemoteConnection connection, boolean isVoip) {} + public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {} + public void onHandleChanged(RemoteConnection connection, Uri handle, int presentation) {} + public void onCallerDisplayNameChanged( + RemoteConnection connection, String callerDisplayName, int presentation) {} + public void onVideoStateChanged(RemoteConnection connection, int videoState) {} + public void onStartActivityFromInCall(RemoteConnection connection, PendingIntent intent) {} + public void onDestroyed(RemoteConnection connection) {} } - private final IConnectionService mConnectionService; + private IConnectionService mConnectionService; private final String mConnectionId; private final Set mListeners = new HashSet<>(); @@ -64,15 +63,35 @@ public final class RemoteConnection { private int mHandlePresentation; private String mCallerDisplayName; private int mCallerDisplayNamePresentation; + private int mFailureCode; + private String mFailureMessage; /** * @hide */ - RemoteConnection(IConnectionService connectionService, String connectionId) { + RemoteConnection(IConnectionService connectionService, ConnectionRequest request, + boolean isIncoming) { mConnectionService = connectionService; - mConnectionId = connectionId; + mConnectionId = request.getCallId(); mConnected = true; + mState = Connection.State.INITIALIZING; + } + + /** + * 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 + * accordingly (moving on to another RemoteConnection, for example) + * + * @param failureCode + * @param failureMessage + */ + private RemoteConnection(int failureCode, String failureMessage) { + this(null, null, true); + mConnected = false; + mState = Connection.State.FAILED; + mFailureCode = failureCode; + mFailureMessage = failureMessage; } public void addListener(Listener listener) { @@ -127,6 +146,14 @@ public final class RemoteConnection { return mVideoState; } + public int getFailureCode() { + return mFailureCode; + } + + public String getFailureMessage() { + return mFailureMessage; + } + public void abort() { try { if (mConnected) { @@ -354,4 +381,24 @@ public final class RemoteConnection { l.onStartActivityFromInCall(this, intent); } } + + /** @hide */ + void setConnectionService(IConnectionService connectionService) { + mConnectionService = connectionService; + mConnectionService = null; + setState(Connection.State.NEW); + } + + /** + * Create a RemoteConnection which is in the {@link Connection.State#FAILED} state. Attempting + * to use it for anything will almost certainly result in bad things happening. Do not do this. + * + * @return a failed {@link RemoteConnection} + * + * @hide + * + */ + public static RemoteConnection failure(int failureCode, String failureMessage) { + return new RemoteConnection(failureCode, failureMessage); + } } diff --git a/telecomm/java/android/telecomm/RemoteConnectionManager.java b/telecomm/java/android/telecomm/RemoteConnectionManager.java index b2d3dc73dff14..3ca68a2d811e8 100644 --- a/telecomm/java/android/telecomm/RemoteConnectionManager.java +++ b/telecomm/java/android/telecomm/RemoteConnectionManager.java @@ -46,17 +46,11 @@ public class RemoteConnectionManager { List getAccounts(Uri handle) { List accountHandles = new LinkedList<>(); - Log.d(this, "Getting accountHandles: " + mRemoteConnectionServices.keySet()); - for (RemoteConnectionService remoteService : mRemoteConnectionServices.values()) { - // TODO(santoscordon): Eventually this will be async. - accountHandles.addAll(remoteService.lookupAccounts(handle)); - } return accountHandles; } - public void createRemoteConnection( + public RemoteConnection createRemoteConnection( ConnectionRequest request, - ConnectionService.CreateConnectionResponse response, boolean isIncoming) { PhoneAccountHandle accountHandle = request.getAccountHandle(); if (accountHandle == null) { @@ -67,9 +61,12 @@ public class RemoteConnectionManager { if (!mRemoteConnectionServices.containsKey(componentName)) { throw new UnsupportedOperationException("accountHandle not supported: " + componentName); - } else { - RemoteConnectionService remoteService = mRemoteConnectionServices.get(componentName); - remoteService.createRemoteConnection(request, response, isIncoming); } + + RemoteConnectionService remoteService = mRemoteConnectionServices.get(componentName); + if (remoteService != null) { + return remoteService.createRemoteConnection(request, isIncoming); + } + return null; } } diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java index c07ff4359d4bf..e6f47d2a7218d 100644 --- a/telecomm/java/android/telecomm/RemoteConnectionService.java +++ b/telecomm/java/android/telecomm/RemoteConnectionService.java @@ -69,8 +69,6 @@ final class RemoteConnectionService implements DeathRecipient { private final ComponentName mComponentName; private String mConnectionId; - private ConnectionRequest mPendingRequest; - private ConnectionService.CreateConnectionResponse mPendingResponse; // Remote connection services only support a single connection. private RemoteConnection mConnection; @@ -84,8 +82,6 @@ final class RemoteConnectionService implements DeathRecipient { ConnectionRequest request = (ConnectionRequest) args.arg1; if (isPendingConnection(request.getCallId())) { ParcelableConnection parcel = (ParcelableConnection) args.arg2; - mConnection = new RemoteConnection( - mConnectionService, request.getCallId()); mConnection.setState(parcel.getState()); mConnection.setCallCapabilities(parcel.getCapabilities()); mConnection.setHandle( @@ -94,9 +90,6 @@ final class RemoteConnectionService implements DeathRecipient { parcel.getCallerDisplayName(), parcel.getCallerDisplayNamePresentation()); // TODO: Do we need to support video providers for remote connections? - - mPendingResponse.onSuccess(request, mConnection); - clearPendingInformation(); } } finally { args.recycle(); @@ -108,9 +101,8 @@ final class RemoteConnectionService implements DeathRecipient { try { ConnectionRequest request = (ConnectionRequest) args.arg1; if (isPendingConnection(request.getCallId())) { - mPendingResponse.onFailure(request, args.argi1, (String) args.arg2); - mConnectionId = null; - clearPendingInformation(); + // TODO: How do we propogate the failure codes? + destroyConnection(); } } finally { args.recycle(); @@ -120,9 +112,7 @@ final class RemoteConnectionService implements DeathRecipient { case MSG_HANDLE_CREATE_CONNECTION_CANCELLED: { ConnectionRequest request = (ConnectionRequest) msg.obj; if (isPendingConnection(request.getCallId())) { - mPendingResponse.onCancel(request); - mConnectionId = null; - clearPendingInformation(); + destroyConnection(); } break; } @@ -431,11 +421,7 @@ final class RemoteConnectionService implements DeathRecipient { release(); } - final void createRemoteConnection( - ConnectionRequest request, - ConnectionService.CreateConnectionResponse response, - boolean isIncoming) { - + final RemoteConnection createRemoteConnection(ConnectionRequest request, boolean isIncoming) { if (mConnectionId == null) { String id = UUID.randomUUID().toString(); ConnectionRequest newRequest = new ConnectionRequest( @@ -445,29 +431,20 @@ final class RemoteConnectionService implements DeathRecipient { request.getHandlePresentation(), request.getExtras(), request.getVideoState()); + mConnection = new RemoteConnection(mConnectionService, request, isIncoming); try { mConnectionService.createConnection(newRequest, isIncoming); mConnectionId = id; - mPendingResponse = response; - mPendingRequest = request; } catch (RemoteException e) { - response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, e.toString()); + mConnection = RemoteConnection.failure(DisconnectCause.ERROR_UNSPECIFIED, + e.toString()); } + return mConnection; } else { - response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, null); + return RemoteConnection.failure(DisconnectCause.ERROR_UNSPECIFIED, null); } } - final List lookupAccounts(Uri handle) { - // TODO(santoscordon): Update this so that is actually calls into the RemoteConnection - // each time. - List accounts = new LinkedList<>(); - accounts.add(new PhoneAccountHandle( - mComponentName, - null /* id */)); - return accounts; - } - /** * Releases the resources associated with this Remote connection service. Should be called when * the remote service is no longer being used. @@ -477,7 +454,7 @@ final class RemoteConnectionService implements DeathRecipient { } private boolean isPendingConnection(String id) { - return TextUtils.equals(mConnectionId, id) && mPendingResponse != null; + return TextUtils.equals(mConnectionId, id); } private boolean isCurrentConnection(Object obj) { @@ -485,11 +462,6 @@ final class RemoteConnectionService implements DeathRecipient { TextUtils.equals(mConnectionId, (String) obj); } - private void clearPendingInformation() { - mPendingRequest = null; - mPendingResponse = null; - } - private void destroyConnection() { mConnection.setDestroyed(); mConnection = null;