am b5d4eaae: am 940e67a8: Merge "ConnectionService API has only one completed callback (1/3)" into lmp-dev

* commit 'b5d4eaae622e2f885235de67568dc9b40ffbb502':
  ConnectionService API has only one completed callback (1/3)
This commit is contained in:
Ihab Awad
2014-08-19 21:37:33 +00:00
committed by Android Git Automerger
9 changed files with 117 additions and 266 deletions

View File

@@ -28828,12 +28828,10 @@ 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 setConferenceableConnections(java.util.List<android.telecomm.Connection>);
method public final void setConnectionService(android.telecomm.ConnectionService);
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();
@@ -28847,10 +28845,8 @@ package android.telecomm {
method public final void startActivityFromInCall(android.app.PendingIntent);
method public static java.lang.String stateToString(int);
field public static final int STATE_ACTIVE = 4; // 0x4
field public static final int STATE_CANCELED = 8; // 0x8
field public static final int STATE_DIALING = 3; // 0x3
field public static final int STATE_DISCONNECTED = 6; // 0x6
field public static final int STATE_FAILED = 7; // 0x7
field public static final int STATE_HOLDING = 5; // 0x5
field public static final int STATE_INITIALIZING = 0; // 0x0
field public static final int STATE_NEW = 1; // 0x1

View File

@@ -36,6 +36,15 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* Represents a connection to a remote endpoint that carries voice traffic.
* <p>
* Implementations create a custom subclass of {@code Connection} and return it to the framework
* as the return value of
* {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
* or
* {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
* Implementations are then responsible for updating the state of the {@code Connection}, and
* must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
* longer used and associated resources may be recovered.
*/
public abstract class Connection {
@@ -53,10 +62,6 @@ public abstract class Connection {
public static final int STATE_DISCONNECTED = 6;
public static final int STATE_FAILED = 7;
public static final int STATE_CANCELED = 8;
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -644,10 +649,6 @@ public abstract class Connection {
return "STATE_HOLDING";
case STATE_DISCONNECTED:
return "DISCONNECTED";
case STATE_FAILED:
return "STATE_FAILED";
case STATE_CANCELED:
return "STATE_CANCELED";
default:
Log.wtf(Connection.class, "Unknown state %d", state);
return "UNKNOWN";
@@ -693,33 +694,6 @@ 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 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 VideoProfile.VideoState#AUDIO_ONLY},
@@ -1094,9 +1068,8 @@ public abstract class Connection {
}
private void setState(int state) {
if (mState == STATE_FAILED || mState == STATE_CANCELED) {
Log.d(this, "Connection already %s; cannot transition out of this state.",
stateToString(mState));
if (mState == STATE_DISCONNECTED && mState != state) {
Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state.");
return;
}
if (mState != state) {
@@ -1109,33 +1082,41 @@ public abstract class Connection {
}
}
static class FailureSignalingConnection extends Connection {
public FailureSignalingConnection(int code, String message) {
setDisconnected(code, message);
}
}
/**
* 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.
* Return a {@code Connection} which represents a failed connection attempt. The returned
* {@code Connection} will have a {@link #getFailureCode()} and {@link #getFailureMessage()}
* as specified, a {@link #getState()} of {@link #STATE_DISCONNECTED}.
* <p>
* The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
* so users of this method need not maintain a reference to its return value to destroy it.
*
* @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.
* @return A {@code Connection} which indicates failure.
*/
public static Connection createFailedConnection(final int code, final String message) {
return new Connection() {{
setFailed(code, message);
}};
return new FailureSignalingConnection(code, message);
}
private static final Connection CANCELED_CONNECTION = new Connection() {{
setCanceled();
}};
private static final Connection CANCELED_CONNECTION =
new FailureSignalingConnection(DisconnectCause.OUTGOING_CANCELED, null);
/**
* 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 {@code Connection} which represents a canceled connection attempt. The returned
* {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of
* that state. This connection should not be used for anything, and no other
* {@code Connection}s should be attempted.
* <p>
* The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
* so users of this method need not maintain a reference to its return value to destroy it.
*
* @return A {@link Connection} which indicates that the underlying call should be canceled.
* @return A {@code Connection} which indicates that the underlying call should be canceled.
*/
public static Connection createCanceledConnection() {
return CANCELED_CONNECTION;

View File

@@ -500,81 +500,26 @@ public abstract class ConnectionService extends Service {
boolean isIncoming) {
Log.d(this, "call %s", request);
final Connection createdConnection;
if (isIncoming) {
createdConnection = onCreateIncomingConnection(callManagerAccount, request);
} else {
createdConnection = onCreateOutgoingConnection(callManagerAccount, request);
}
Connection createdConnection = isIncoming
? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
if (createdConnection != null) {
Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
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());
Log.d(this, "adapter handleCreateConnectionFailed %s",
callId);
mAdapter.handleCreateConnectionFailed(
callId,
request,
c.getFailureCode(),
c.getFailureMessage());
break;
case Connection.STATE_CANCELED:
Log.d(this, "adapter handleCreateConnectionCanceled %s",
callId);
mAdapter.handleCreateConnectionCancelled(callId, request);
break;
case Connection.STATE_INITIALIZING:
Log.d(this, "State changed to STATE_INITIALIZING; ignoring");
return; // Don't want to stop listening on this state transition.
}
c.removeConnectionListener(this);
}
@Override
public void onDestroyed(Connection c) {
// Listen to onDestroy in case the connection is destroyed before
// transitioning to another state.
c.removeConnectionListener(this);
}
});
Log.d(this, "Connection created in state INITIALIZING");
connectionCreated(callId, request, createdConnection);
} else if (createdConnection.getState() == Connection.STATE_CANCELED) {
// Tell telecomm not to attempt any more services.
mAdapter.handleCreateConnectionCancelled(callId, request);
} else if (createdConnection.getState() == Connection.STATE_FAILED) {
mAdapter.handleCreateConnectionFailed(
callId,
request,
createdConnection.getFailureCode(),
createdConnection.getFailureMessage());
} else {
connectionCreated(callId, request, createdConnection);
}
} else {
if (createdConnection == null) {
Log.d(this, "adapter handleCreateConnectionComplete CANCELED %s", callId);
// Tell telecomm to try a different service.
Log.d(this, "adapter handleCreateConnectionFailed %s", callId);
mAdapter.handleCreateConnectionFailed(
callId,
request,
DisconnectCause.ERROR_UNSPECIFIED,
null);
createdConnection = Connection.createCanceledConnection();
}
connectionCreated(callId, request, createdConnection);
}
private void connectionCreated(
String callId,
ConnectionRequest request,
Connection connection) {
addConnection(callId, connection);
if (!(connection instanceof Connection.FailureSignalingConnection)) {
addConnection(callId, connection);
}
Uri handle = connection.getHandle();
String number = handle == null ? "null" : handle.getSchemeSpecificPart();
Log.v(this, "connectionCreated, parcelableconnection: %s, %d, %s",
@@ -583,7 +528,7 @@ public abstract class ConnectionService extends Service {
PhoneCapabilities.toString(connection.getCallCapabilities()));
Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
mAdapter.handleCreateConnectionSuccessful(
mAdapter.handleCreateConnectionComplete(
callId,
request,
new ParcelableConnection(
@@ -599,7 +544,9 @@ public abstract class ConnectionService extends Service {
connection.getVideoState(),
connection.isRequestingRingback(),
connection.getAudioModeIsVoip(),
connection.getStatusHints()));
connection.getStatusHints(),
connection.getFailureCode(),
connection.getFailureMessage()));
}
private void abort(String callId) {
@@ -699,7 +646,8 @@ public abstract class ConnectionService extends Service {
final List<ComponentName> componentNames,
final List<IBinder> services) {
mHandler.post(new Runnable() {
@Override public void run() {
@Override
public void run() {
for (int i = 0; i < componentNames.size() && i < services.size(); i++) {
mRemoteConnectionManager.addConnectionService(
componentNames.get(i),
@@ -714,7 +662,8 @@ public abstract class ConnectionService extends Service {
@Override
public void onError() {
mHandler.post(new Runnable() {
@Override public void run() {
@Override
public void run() {
mAreAccountsInitialized = true;
}
});

View File

@@ -76,37 +76,13 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
}
void handleCreateConnectionSuccessful(
void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection connection) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.handleCreateConnectionSuccessful(id, request, connection);
} catch (RemoteException e) {
}
}
}
void handleCreateConnectionFailed(
String id,
ConnectionRequest request,
int errorCode,
String errorMsg) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.handleCreateConnectionFailed(id, request, errorCode, errorMsg);
} catch (RemoteException e) {
}
}
}
void handleCreateConnectionCancelled(
String id,
ConnectionRequest request) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.handleCreateConnectionCancelled(id, request);
adapter.handleCreateConnectionComplete(id, request, connection);
} catch (RemoteException e) {
}
}

View File

@@ -38,29 +38,27 @@ import java.util.List;
* @hide
*/
final class ConnectionServiceAdapterServant {
private static final int MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL = 1;
private static final int MSG_HANDLE_CREATE_CONNECTION_FAILED = 2;
private static final int MSG_HANDLE_CREATE_CONNECTION_CANCELLED = 3;
private static final int MSG_SET_ACTIVE = 4;
private static final int MSG_SET_RINGING = 5;
private static final int MSG_SET_DIALING = 6;
private static final int MSG_SET_DISCONNECTED = 7;
private static final int MSG_SET_ON_HOLD = 8;
private static final int MSG_SET_REQUESTING_RINGBACK = 9;
private static final int MSG_SET_CALL_CAPABILITIES = 10;
private static final int MSG_SET_IS_CONFERENCED = 11;
private static final int MSG_ADD_CONFERENCE_CALL = 12;
private static final int MSG_REMOVE_CALL = 13;
private static final int MSG_ON_POST_DIAL_WAIT = 14;
private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 15;
private static final int MSG_SET_VIDEO_STATE = 16;
private static final int MSG_SET_VIDEO_CALL_PROVIDER = 17;
private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 18;
private static final int MSG_SET_STATUS_HINTS = 19;
private static final int MSG_SET_HANDLE = 20;
private static final int MSG_SET_CALLER_DISPLAY_NAME = 21;
private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 22;
private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 23;
private static final int MSG_HANDLE_CREATE_CONNECTION_COMPLETE = 1;
private static final int MSG_SET_ACTIVE = 2;
private static final int MSG_SET_RINGING = 3;
private static final int MSG_SET_DIALING = 4;
private static final int MSG_SET_DISCONNECTED = 5;
private static final int MSG_SET_ON_HOLD = 6;
private static final int MSG_SET_REQUESTING_RINGBACK = 7;
private static final int MSG_SET_CALL_CAPABILITIES = 8;
private static final int MSG_SET_IS_CONFERENCED = 9;
private static final int MSG_ADD_CONFERENCE_CALL = 10;
private static final int MSG_REMOVE_CALL = 11;
private static final int MSG_ON_POST_DIAL_WAIT = 12;
private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 13;
private static final int MSG_SET_VIDEO_STATE = 14;
private static final int MSG_SET_VIDEO_CALL_PROVIDER = 15;
private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 16;
private static final int MSG_SET_STATUS_HINTS = 17;
private static final int MSG_SET_HANDLE = 18;
private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 20;
private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 21;
private final IConnectionServiceAdapter mDelegate;
@@ -76,10 +74,10 @@ final class ConnectionServiceAdapterServant {
// Internal method defined to centralize handling of RemoteException
private void internalHandleMessage(Message msg) throws RemoteException {
switch (msg.what) {
case MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL: {
case MSG_HANDLE_CREATE_CONNECTION_COMPLETE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
mDelegate.handleCreateConnectionSuccessful(
mDelegate.handleCreateConnectionComplete(
(String) args.arg1,
(ConnectionRequest) args.arg2,
(ParcelableConnection) args.arg3);
@@ -88,30 +86,6 @@ final class ConnectionServiceAdapterServant {
}
break;
}
case MSG_HANDLE_CREATE_CONNECTION_FAILED: {
SomeArgs args = (SomeArgs) msg.obj;
try {
mDelegate.handleCreateConnectionFailed(
(String) args.arg1,
(ConnectionRequest) args.arg2,
args.argi1,
(String) args.arg3);
} finally {
args.recycle();
}
break;
}
case MSG_HANDLE_CREATE_CONNECTION_CANCELLED: {
SomeArgs args = (SomeArgs) msg.obj;
try {
mDelegate.handleCreateConnectionCancelled(
(String) args.arg1,
(ConnectionRequest) args.arg2);
} finally {
args.recycle();
}
break;
}
case MSG_SET_ACTIVE:
mDelegate.setActive((String) msg.obj);
break;
@@ -244,7 +218,7 @@ final class ConnectionServiceAdapterServant {
private final IConnectionServiceAdapter mStub = new IConnectionServiceAdapter.Stub() {
@Override
public void handleCreateConnectionSuccessful(
public void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection connection) {
@@ -252,31 +226,7 @@ final class ConnectionServiceAdapterServant {
args.arg1 = id;
args.arg2 = request;
args.arg3 = connection;
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL, args).sendToTarget();
}
@Override
public void handleCreateConnectionFailed(
String id,
ConnectionRequest request,
int errorCode,
String errorMessage) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = id;
args.arg2 = request;
args.argi1 = errorCode;
args.arg3 = errorMessage;
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_FAILED, args).sendToTarget();
}
@Override
public void handleCreateConnectionCancelled(
String id,
ConnectionRequest request) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = id;
args.arg2 = request;
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_CANCELLED, args).sendToTarget();
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
}
@Override

View File

@@ -41,6 +41,8 @@ public final class ParcelableConnection implements Parcelable {
private boolean mRequestingRingback;
private boolean mAudioModeIsVoip;
private StatusHints mStatusHints;
private int mFailureCode;
private String mFailureMessage;
/** @hide */
public ParcelableConnection(
@@ -55,7 +57,9 @@ public final class ParcelableConnection implements Parcelable {
int videoState,
boolean requestingRingback,
boolean audioModeIsVoip,
StatusHints statusHints) {
StatusHints statusHints,
int failureCode,
String failureMessage) {
mPhoneAccount = phoneAccount;
mState = state;
mCapabilities = capabilities;
@@ -68,6 +72,8 @@ public final class ParcelableConnection implements Parcelable {
mRequestingRingback = requestingRingback;
mAudioModeIsVoip = audioModeIsVoip;
mStatusHints = statusHints;
mFailureCode = failureCode;
mFailureMessage = failureMessage;
}
public PhoneAccountHandle getPhoneAccount() {
@@ -119,6 +125,14 @@ public final class ParcelableConnection implements Parcelable {
return mStatusHints;
}
public final int getFailureCode() {
return mFailureCode;
}
public final String getFailureMessage() {
return mFailureMessage;
}
@Override
public String toString() {
return new StringBuilder()
@@ -150,6 +164,8 @@ public final class ParcelableConnection implements Parcelable {
boolean requestingRingback = source.readByte() == 1;
boolean audioModeIsVoip = source.readByte() == 1;
StatusHints statusHints = source.readParcelable(classLoader);
int disconnectCauseCode = source.readInt();
String disconnectCauseMessage = source.readString();
return new ParcelableConnection(
phoneAccount,
@@ -163,7 +179,9 @@ public final class ParcelableConnection implements Parcelable {
videoState,
requestingRingback,
audioModeIsVoip,
statusHints);
statusHints,
disconnectCauseCode,
disconnectCauseMessage);
}
@Override
@@ -194,5 +212,7 @@ public final class ParcelableConnection implements Parcelable {
destination.writeByte((byte) (mRequestingRingback ? 1 : 0));
destination.writeByte((byte) (mAudioModeIsVoip ? 1 : 0));
destination.writeParcelable(mStatusHints, 0);
destination.writeInt(mFailureCode);
destination.writeString(mFailureMessage);
}
}

View File

@@ -233,9 +233,9 @@ public final class RemoteConnection {
RemoteConnection(int failureCode, String failureMessage) {
this("NULL", null, null);
mConnected = false;
mState = Connection.STATE_FAILED;
mFailureCode = failureCode;
mFailureMessage = failureMessage;
mState = Connection.STATE_DISCONNECTED;
mFailureCode = DisconnectCause.OUTGOING_FAILURE;
mFailureMessage = failureMessage + " original code = " + failureCode;
}
/**
@@ -675,8 +675,9 @@ public final class RemoteConnection {
}
/**
* 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.
* Create a RemoteConnection represents a failure, and which will be in
* {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost
* certainly result in bad things happening. Do not do this.
*
* @return a failed {@link RemoteConnection}
*

View File

@@ -48,7 +48,7 @@ final class RemoteConnectionService {
private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
@Override
public void handleCreateConnectionSuccessful(
public void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection parcel) {
@@ -56,6 +56,7 @@ final class RemoteConnectionService {
findConnectionForAction(id, "handleCreateConnectionSuccessful");
if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
mPendingConnections.remove(connection);
// Unconditionally initialize the connection ...
connection.setState(parcel.getState());
connection.setCallCapabilities(parcel.getCapabilities());
connection.setHandle(
@@ -64,28 +65,14 @@ final class RemoteConnectionService {
parcel.getCallerDisplayName(),
parcel.getCallerDisplayNamePresentation());
// TODO: Do we need to support video providers for remote connections?
if (connection.getState() == Connection.STATE_DISCONNECTED) {
// ... then, if it was created in a disconnected state, that indicates
// failure on the providing end, so immediately mark it destroyed
connection.setDestroyed();
}
}
}
@Override
public void handleCreateConnectionFailed(
String id,
ConnectionRequest request,
int errorCode,
String errorMessage) {
// TODO: How do we propagate the failure codes?
findConnectionForAction(id, "handleCreateConnectionFailed")
.setDestroyed();
}
@Override
public void handleCreateConnectionCancelled(
String id,
ConnectionRequest request) {
findConnectionForAction(id, "handleCreateConnectionCancelled")
.setDestroyed();
}
@Override
public void setActive(String callId) {
findConnectionForAction(callId, "setActive")

View File

@@ -34,20 +34,11 @@ import com.android.internal.telecomm.RemoteServiceCallback;
* {@hide}
*/
oneway interface IConnectionServiceAdapter {
void handleCreateConnectionSuccessful(
void handleCreateConnectionComplete(
String callId,
in ConnectionRequest request,
in ParcelableConnection connection);
void handleCreateConnectionFailed(
String callId,
in ConnectionRequest request,
int errorCode, String errorMessage);
void handleCreateConnectionCancelled(
String callId,
in ConnectionRequest request);
void setActive(String callId);
void setRinging(String callId);