Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf11f98d authored by Evan Charlton's avatar Evan Charlton
Browse files

Make creating the Connection synchronous

Get rid of CreateConnectionResponse and have the ConnectionService
return the built connection instead.

Change-Id: Ibbf896e5b188b98eb386d6624d3a5d5cacf49922
parent ca7a229e
Loading
Loading
Loading
Loading
+37 −24
Original line number Diff line number Diff line
@@ -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 {
+119 −13
Original line number Diff line number Diff line
@@ -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) {
        if (mState == State.FAILED || mState == State.CANCELED) {
            Log.d(this, "Connection already %s; cannot transition out of this state.",
                    stateToString(mState));
            return;
        }
        if (mState != state) {
            Log.d(this, "setState: %s", stateToString(state));
        this.mState = 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;
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -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
+77 −61
Original line number Diff line number Diff line
@@ -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,13 +425,60 @@ 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) {
    private void createConnection(final ConnectionRequest request, boolean isIncoming) {
        Log.d(this, "call %s", request);

        final Connection createdConnection;
        if (isIncoming) {
            createdConnection = onCreateIncomingConnection(request);
        } else {
            createdConnection = onCreateOutgoingConnection(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);
            }
        } else {
            // 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,
@@ -448,25 +495,6 @@ public abstract class ConnectionService extends Service {
                        connection.getVideoState()));
    }

            @Override
            public void onFailure(ConnectionRequest request, int code, String msg) {
                // Tell telecomm to try a different service.
                mAdapter.handleCreateConnectionFailed(request, code, msg);
            }

            @Override
            public void onCancel(ConnectionRequest request) {
                // Tell telecomm not to attempt any more services.
                mAdapter.handleCreateConnectionCancelled(request);
            }
        };
        if (isIncoming) {
            onCreateIncomingConnection(originalRequest, response);
        } else {
            onCreateOutgoingConnection(originalRequest, response);
        }
    }

    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.
     * @param callback A callback for providing the result.
     *
     * @return The {@link Connection} object to satisfy this request,
     * or null to not handle the call.
     *
     */
    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
+67 −20

File changed.

Preview size limit exceeded, changes collapsed.

Loading