Make creating the Connection synchronous
Get rid of CreateConnectionResponse and have the ConnectionService return the built connection instead. Change-Id: Ibbf896e5b188b98eb386d6624d3a5d5cacf49922
This commit is contained in:
@@ -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<android.telecomm.Connection> 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<android.telecomm.RemoteConnection>);
|
||||
method public final void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse<android.telecomm.RemoteConnection>);
|
||||
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<android.telecomm.Connection> getAllConnections();
|
||||
method public final void lookupRemoteAccounts(android.net.Uri, android.telecomm.SimpleResponse<android.net.Uri, java.util.List<android.telecomm.PhoneAccountHandle>>);
|
||||
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<java.lang.String, android.telecomm.Connection>);
|
||||
method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse<android.telecomm.Connection>);
|
||||
method public void onCreateOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse<android.telecomm.Connection>);
|
||||
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 {
|
||||
|
||||
@@ -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<Listener> 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.
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Connection>() {
|
||||
@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<Uri, List<PhoneAccountHandle>> 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<RemoteConnection> response) {
|
||||
mRemoteConnectionManager.createRemoteConnection(request, response, true);
|
||||
public final RemoteConnection createRemoteIncomingConnection(ConnectionRequest request) {
|
||||
return mRemoteConnectionManager.createRemoteConnection(request, true);
|
||||
}
|
||||
|
||||
public final void createRemoteOutgoingConnection(
|
||||
ConnectionRequest request,
|
||||
CreateConnectionResponse<RemoteConnection> 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<Connection> 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<Connection> callback) {}
|
||||
public Connection onCreateOutgoingConnection(ConnectionRequest request) { return null; }
|
||||
|
||||
/**
|
||||
* Returns a new or existing conference connection when the the user elects to convert the
|
||||
|
||||
@@ -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<Listener> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,17 +46,11 @@ public class RemoteConnectionManager {
|
||||
|
||||
List<PhoneAccountHandle> getAccounts(Uri handle) {
|
||||
List<PhoneAccountHandle> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +69,6 @@ final class RemoteConnectionService implements DeathRecipient {
|
||||
private final ComponentName mComponentName;
|
||||
|
||||
private String mConnectionId;
|
||||
private ConnectionRequest mPendingRequest;
|
||||
private ConnectionService.CreateConnectionResponse<RemoteConnection> 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<RemoteConnection> 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<PhoneAccountHandle> lookupAccounts(Uri handle) {
|
||||
// TODO(santoscordon): Update this so that is actually calls into the RemoteConnection
|
||||
// each time.
|
||||
List<PhoneAccountHandle> 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;
|
||||
|
||||
Reference in New Issue
Block a user