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

Commit a611e457 authored by Ihab Awad's avatar Ihab Awad Committed by Android (Google) Code Review
Browse files

Merge "Publish new Telecomm API for Connection Services"

parents 3a9f0175 542e0ea8
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
@@ -26738,6 +26738,83 @@ package android.telecomm {
    enum_constant public static final android.telecomm.CallState RINGING;
  }
  public abstract class Connection {
    ctor protected Connection();
    method public final android.telecomm.CallAudioState getCallAudioState();
    method public final android.net.Uri getHandle();
    method protected void onAbort();
    method protected void onAnswer();
    method protected void onDisconnect();
    method protected void onHold();
    method protected void onPlayDtmfTone(char);
    method protected void onReject();
    method protected void onSetAudioState(android.telecomm.CallAudioState);
    method protected void onSetSignal(android.os.Bundle);
    method protected void onStopDtmfTone();
    method protected void onUnhold();
    method protected void setActive();
    method public void setAudioState(android.telecomm.CallAudioState);
    method protected void setDialing();
    method protected void setDisconnected(int, java.lang.String);
    method protected void setHandle(android.net.Uri);
    method protected void setOnHold();
    method protected void setRinging();
    method public static java.lang.String stateToString(int);
  }
  public static abstract interface Connection.Listener {
    method public abstract void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
    method public abstract void onDestroyed(android.telecomm.Connection);
    method public abstract void onDisconnected(android.telecomm.Connection, int, java.lang.String);
    method public abstract void onHandleChanged(android.telecomm.Connection, android.net.Uri);
    method public abstract void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
    method public abstract void onStateChanged(android.telecomm.Connection, int);
  }
  public static class Connection.ListenerBase implements android.telecomm.Connection.Listener {
    ctor public Connection.ListenerBase();
    method public void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
    method public void onDestroyed(android.telecomm.Connection);
    method public void onDisconnected(android.telecomm.Connection, int, java.lang.String);
    method public void onHandleChanged(android.telecomm.Connection, android.net.Uri);
    method public void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
    method public void onStateChanged(android.telecomm.Connection, int);
  }
  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
  }
  public final class ConnectionRequest {
    ctor public ConnectionRequest(android.net.Uri, android.os.Bundle);
    method public android.os.Bundle getExtras();
    method public android.net.Uri getHandle();
  }
  public abstract class ConnectionService extends android.telecomm.CallService {
    ctor public ConnectionService();
    method public final void abort(java.lang.String);
    method public final void answer(java.lang.String);
    method public final void call(android.telecomm.CallInfo);
    method public final void disconnect(java.lang.String);
    method public final void hold(java.lang.String);
    method public final void isCompatibleWith(android.telecomm.CallInfo);
    method public final void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
    method public void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
    method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
    method public void onFindSubscriptions(android.net.Uri, android.telecomm.Response<android.net.Uri, android.telecomm.Subscription>);
    method public final void playDtmfTone(java.lang.String, char);
    method public final void reject(java.lang.String);
    method public final void setIncomingCallId(java.lang.String, android.os.Bundle);
    method public final void stopDtmfTone(java.lang.String);
    method public final void unhold(java.lang.String);
  }
  public class GatewayInfo implements android.os.Parcelable {
    method public int describeContents();
    method public android.net.Uri getGatewayHandle();
@@ -26789,6 +26866,18 @@ package android.telecomm {
    method protected abstract void updateCall(android.telecomm.InCallCall);
  }
  public abstract interface Response {
    method public abstract void onError(IN, java.lang.String);
    method public abstract void onResult(IN, OUT...);
  }
  public class Subscription implements android.os.Parcelable {
    ctor public Subscription();
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public final class TelecommConstants {
    ctor public TelecommConstants();
    field public static final java.lang.String ACTION_CALL_SERVICE;
+412 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telecomm;

import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

import java.util.HashSet;
import java.util.Set;

/**
 * Represents a connection to a remote endpoint that carries voice traffic.
 */
public abstract class Connection {

    private static String TAG = Connection.class.getSimpleName();

    public interface Listener {
        void onStateChanged(Connection c, int state);
        void onAudioStateChanged(Connection c, CallAudioState state);
        void onHandleChanged(Connection c, Uri newHandle);
        void onSignalChanged(Connection c, Bundle details);
        void onDisconnected(Connection c, int cause, String message);
        void onDestroyed(Connection c);
    }

    public static class ListenerBase implements Listener {
        /** {@inheritDoc} */
        @Override
        public void onStateChanged(Connection c, int state) {}

        /** {@inheritDoc} */
         @Override
        public void onAudioStateChanged(Connection c, CallAudioState state) {}

        /** {@inheritDoc} */
        @Override
        public void onHandleChanged(Connection c, Uri newHandle) {}

        /** {@inheritDoc} */
        @Override
        public void onSignalChanged(Connection c, Bundle details) {}

        /** {@inheritDoc} */
        @Override
        public void onDisconnected(Connection c, int cause, String message) {}

        /** {@inheritDoc} */
        @Override
        public void onDestroyed(Connection c) {}
    }

    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;
    }

    private final Set<Listener> mListeners = new HashSet<>();
    private int mState = State.NEW;
    private CallAudioState mCallAudioState;
    private Uri mHandle;

    /**
     * Create a new Connection.
     */
    protected Connection() {}

    /**
     * @return The handle (e.g., phone number) to which this Connection
     *         is currently communicating.
     */
    public final Uri getHandle() {
        return mHandle;
    }

    /**
     * @return The state of this Connection.
     *
     * @hide
     */
    public final int getState() {
        return mState;
    }

    /**
     * @return The audio state of the call, describing how its audio is currently
     *         being routed by the system. This is {@code null} if this Connection
     *         does not directly know about its audio state.
     */
    public final CallAudioState getCallAudioState() {
        return mCallAudioState;
    }

    /**
     * Assign a listener to be notified of state changes.
     *
     * @param l A listener.
     * @return This Connection.
     *
     * @hide
     */
    public final Connection addConnectionListener(Listener l) {
        mListeners.add(l);
        return this;
    }

    /**
     * Remove a previously assigned listener that was being notified of state changes.
     *
     * @param l A Listener.
     * @return This Connection.
     *
     * @hide
     */
    public final Connection removeConnectionListener(Listener l) {
        mListeners.remove(l);
        return this;
    }

    /**
     * Play a DTMF tone in this Connection.
     *
     * @param c A DTMF character.
     *
     * @hide
     */
    public final void playDtmfTone(char c) {
        Log.d(TAG, "playDtmfTone " + c);
        onPlayDtmfTone(c);
    }

    /**
     * Stop any DTMF tones which may be playing in this Connection.
     *
     * @hide
     */
    public final void stopDtmfTone() {
        Log.d(TAG, "stopDtmfTone");
        onStopDtmfTone();
    }

    /**
     * Disconnect this Connection. If and when the Connection can comply with
     * this request, it will transition to the {@link State#DISCONNECTED}
     * state and notify its listeners.
     *
     * @hide
     */
    public final void disconnect() {
        Log.d(TAG, "disconnect");
        onDisconnect();
    }

    /**
     * Abort this Connection. The Connection will immediately transition to
     * the {@link State#DISCONNECTED} state, and send no notifications of this
     * or any other future events.
     *
     * @hide
     */
    public final void abort() {
        Log.d(TAG, "abort");
        onAbort();
    }

    /**
     * Place this Connection on hold. If and when the Connection can comply with
     * this request, it will transition to the {@link State#HOLDING}
     * state and notify its listeners.
     *
     * @hide
     */
    public final void hold() {
        Log.d(TAG, "hold");
        onHold();
    }

    /**
     * Un-hold this Connection. If and when the Connection can comply with
     * this request, it will transition to the {@link State#ACTIVE}
     * state and notify its listeners.
     *
     * @hide
     */
    public final void unhold() {
        Log.d(TAG, "unhold");
        onUnhold();
    }

    /**
     * Accept a {@link State#RINGING} Connection. If and when the Connection
     * can comply with this request, it will transition to the {@link State#ACTIVE}
     * state and notify its listeners.
     *
     * @hide
     */
    public final void answer() {
        Log.d(TAG, "answer");
        if (mState == State.RINGING) {
            onAnswer();
        }
    }

    /**
     * Reject a {@link State#RINGING} Connection. If and when the Connection
     * can comply with this request, it will transition to the {@link State#ACTIVE}
     * state and notify its listeners.
     *
     * @hide
     */
    public final void reject() {
        Log.d(TAG, "reject");
        if (mState == State.RINGING) {
            onReject();
        }
    }

    /**
     * Inform this Connection that the state of its audio output has been changed externally.
     *
     * @param state The new audio state.
     */
    public void setAudioState(CallAudioState state) {
        Log.d(TAG, "setAudioState " + state);
        onSetAudioState(state);
    }

    /**
     * @param state An integer value from {@link State}.
     * @return A string representation of the value.
     */
    public static String stateToString(int state) {
        switch (state) {
            case State.NEW:
                return "NEW";
            case State.RINGING:
                return "RINGING";
            case State.DIALING:
                return "DIALING";
            case State.ACTIVE:
                return "ACTIVE";
            case State.HOLDING:
                return "HOLDING";
            case State.DISCONNECTED:
                return "DISCONNECTED";
            default:
                Log.wtf(TAG, "Unknown state " + state);
                return "UNKNOWN";
        }
    }

    /**
     * Sets the value of the {@link #getHandle()} property and notifies listeners.
     *
     * @param handle The new handle.
     */
    protected void setHandle(Uri handle) {
        Log.d(TAG, "setHandle " + handle);
        // TODO: Enforce super called
        mHandle = handle;
        for (Listener l : mListeners) {
            l.onHandleChanged(this, handle);
        }
    }

    /**
     * Sets state to active (e.g., an ongoing call where two or more parties can actively
     * communicate).
     */
    protected void setActive() {
        setState(State.ACTIVE);
    }

    /**
     * Sets state to ringing (e.g., an inbound ringing call).
     */
    protected void setRinging() {
        setState(State.RINGING);
    }

    /**
     * Sets state to dialing (e.g., dialing an outbound call).
     */
    protected void setDialing() {
        setState(State.DIALING);
    }

    /**
     * Sets state to be on hold.
     */
    protected void setOnHold() {
        setState(State.HOLDING);
    }

    /**
     * Sets state to disconnected. This will first notify listeners with an
     * {@link Listener#onStateChanged(Connection, int)} event, then will fire an
     * {@link Listener#onDisconnected(Connection, int, String)} event with additional
     * details.
     *
     * @param cause The reason for the disconnection, any of
     *         {@link android.telephony.DisconnectCause}.
     * @param message Optional call-service-provided message about the disconnect.
     */
    protected void setDisconnected(int cause, String message) {
        setState(State.DISCONNECTED);
        Log.d(TAG, "Disconnected with cause " + cause + " message " + message);
        for (Listener l : mListeners) {
            l.onDisconnected(this, cause, message);
        }
    }

    /**
     * Notifies this Connection and listeners that the {@link #getCallAudioState()} property
     * has a new value.
     *
     * @param state The new call audio state.
     */
    protected void onSetAudioState(CallAudioState state) {
        // TODO: Enforce super called
        this.mCallAudioState = state;
        for (Listener l : mListeners) {
            l.onAudioStateChanged(this, state);
        }
    }

    /**
     * Notifies this Connection and listeners of a change in the current signal levels
     * for the underlying data transport.
     *
     * @param details A {@link android.os.Bundle} containing details of the current level.
     */
    protected void onSetSignal(Bundle details) {
        // TODO: Enforce super called
        for (Listener l : mListeners) {
            l.onSignalChanged(this, details);
        }
    }

    /**
     * Notifies this Connection of a request to play a DTMF tone.
     *
     * @param c A DTMF character.
     */
    protected void onPlayDtmfTone(char c) {}

    /**
     * Notifies this Connection of a request to stop any currently playing DTMF tones.
     */
    protected void onStopDtmfTone() {}

    /**
     * Notifies this Connection of a request to disconnect.
     */
    protected void onDisconnect() {}

    /**
     * Notifies this Connection of a request to abort.
     */
    protected void onAbort() {}

    /**
     * Notifies this Connection of a request to hold.
     */
    protected void onHold() {}

    /**
     * Notifies this Connection of a request to exit a hold state.
     */
    protected void onUnhold() {}

    /**
     * Notifies this Connection, which is in {@link State#RINGING}, of
     * a request to accept.
     */
    protected void onAnswer() {}

    /**
     * Notifies this Connection, which is in {@link State#RINGING}, of
     * a request to reject.
     */
    protected void onReject() {}

    private void setState(int state) {
        Log.d(TAG, "setState: " + stateToString(state));
        this.mState = state;
        for (Listener l : mListeners) {
            l.onStateChanged(this, state);
        }
    }
}
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telecomm;

import android.os.Bundle;
import android.net.Uri;

/**
 * Simple data container encapsulating a request to some entity to
 * create a new {@link Connection}.
 */
public final class ConnectionRequest {

    // TODO: Token to limit recursive invocations
    // TODO: Consider upgrading "mHandle" to ordered list of handles, indicating a set of phone
    //         numbers that would satisfy the client's needs, in order of preference
    private final Uri mHandle;
    private final Bundle mExtras;

    public ConnectionRequest(Uri handle, Bundle extras) {
        mHandle = handle; mExtras = extras;
    }

    /**
     * The handle (e.g., phone number) to which the {@link Connection} is to connect.
     */
    public Uri getHandle() { return mHandle; }

    /**
     * Application-specific extra data. Used for passing back information from an incoming
     * call {@code Intent}, and for any proprietary extensions arranged between a client
     * and servant {@code ConnectionService} which agree on a vocabulary for such data.
     */
    public Bundle getExtras() { return mExtras; }

    public String toString() {
        return String.format("PhoneConnectionRequest %s %s",
                mHandle == null
                        ? Uri.EMPTY
                        : ConnectionService.toLogSafePhoneNumber(mHandle.toString()),
                mExtras == null ? "" : mExtras);
    }
}
+345 −0

File added.

Preview size limit exceeded, changes collapsed.

+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telecomm;

/**
 * Used to inform a client of asynchronously returned results.
 */
public interface Response<IN, OUT> {

    /**
     * Provide a set of results.
     *
     * @param request The original request.
     * @param result The results.
     */
    void onResult(IN request, OUT... result);

    /**
     * Indicates the inability to provide results.
     *
     * @param request The original request.
     * @param reason The reason for the failure.
     */
    void onError(IN request, String reason);
}
Loading