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

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

Merge "Support Conferences in Remote Connections" into lmp-dev

parents 339227da b8e85c74
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -28596,6 +28596,7 @@ package android.telecomm {
  public abstract class ConnectionService extends android.app.Service {
    ctor public ConnectionService();
    method public final void addConference(android.telecomm.Conference);
    method public final void conferenceRemoteConnections(android.telecomm.RemoteConnection, android.telecomm.RemoteConnection);
    method public final android.telecomm.RemoteConnection createRemoteIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
    method public final android.telecomm.RemoteConnection createRemoteOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
    method public final java.util.Collection<android.telecomm.Connection> getAllConnections();
@@ -28605,6 +28606,7 @@ package android.telecomm {
    method public void onConnectionRemoved(android.telecomm.Connection);
    method public android.telecomm.Connection onCreateIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
    method public android.telecomm.Connection onCreateOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
    method public void onRemoteConferenceAdded(android.telecomm.RemoteConference);
    field public static final java.lang.String SERVICE_INTERFACE = "android.telecomm.ConnectionService";
  }
@@ -28681,6 +28683,30 @@ package android.telecomm {
    field public static final int UNKNOWN = 3; // 0x3
  }
  public final class RemoteConference {
    method public final void addListener(android.telecomm.RemoteConference.Listener);
    method public void disconnect();
    method public final int getCallCapabilities();
    method public final java.util.List<android.telecomm.RemoteConnection> getConnections();
    method public int getDisconnectCause();
    method public java.lang.String getDisconnectMessage();
    method public final int getState();
    method public void hold();
    method public final void removeListener(android.telecomm.RemoteConference.Listener);
    method public void separate(android.telecomm.RemoteConnection);
    method public void unhold();
  }
  public static abstract class RemoteConference.Listener {
    ctor public RemoteConference.Listener();
    method public void onCapabilitiesChanged(android.telecomm.RemoteConference, int);
    method public void onConnectionAdded(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
    method public void onConnectionRemoved(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
    method public void onDestroyed(android.telecomm.RemoteConference);
    method public void onDisconnected(android.telecomm.RemoteConference, int, java.lang.String);
    method public void onStateChanged(android.telecomm.RemoteConference, int, int);
  }
  public final class RemoteConnection {
    method public void abort();
    method public void addListener(android.telecomm.RemoteConnection.Listener);
@@ -28691,6 +28717,8 @@ package android.telecomm {
    method public java.lang.String getCallerDisplayName();
    method public int getCallerDisplayNamePresentation();
    method public java.util.List<android.telecomm.RemoteConnection> getChildren();
    method public android.telecomm.RemoteConference getConference();
    method public java.util.List<android.telecomm.RemoteConnection> getConferenceableConnections();
    method public int getDisconnectCauseCode();
    method public java.lang.String getDisconnectCauseMessage();
    method public int getFailureCode();
@@ -28717,6 +28745,7 @@ package android.telecomm {
    method public void onCallCapabilitiesChanged(android.telecomm.RemoteConnection, int);
    method public void onCallerDisplayNameChanged(android.telecomm.RemoteConnection, java.lang.String, int);
    method public void onChildrenChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
    method public void onConferenceChanged(android.telecomm.RemoteConnection, android.telecomm.RemoteConference);
    method public void onConferenceableConnectionsChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
    method public void onDestroyed(android.telecomm.RemoteConnection);
    method public void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String);
+3 −5
Original line number Diff line number Diff line
@@ -18,9 +18,7 @@ package android.telecomm;

import android.telephony.DisconnectCause;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -43,7 +41,7 @@ public abstract class Conference {

    private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
    private final List<Connection> mChildConnections = new CopyOnWriteArrayList<>();
    private final List<Connection> mUnmodifiableChildConnection =
    private final List<Connection> mUnmodifiableChildConnections =
            Collections.unmodifiableList(mChildConnections);

    private PhoneAccountHandle mPhoneAccount;
@@ -61,7 +59,7 @@ public abstract class Conference {
    }

    public final List<Connection> getConnections() {
        return mUnmodifiableChildConnection;
        return mUnmodifiableChildConnections;
    }

    public final int getState() {
@@ -125,7 +123,7 @@ public abstract class Conference {
    }

    /**
     * Sets the cabilities of a conference.
     * Sets the capabilities of a conference.
     */
    public final void setCapabilities(int capabilities) {
        if (capabilities != mCapabilities) {
+38 −12
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
@@ -79,7 +78,8 @@ public abstract class ConnectionService extends Service {
    private final Map<Connection, String> mIdByConnection = new HashMap<>();
    private final Map<String, Conference> mConferenceById = new HashMap<>();
    private final Map<Conference, String> mIdByConference = new HashMap<>();
    private final RemoteConnectionManager mRemoteConnectionManager = new RemoteConnectionManager();
    private final RemoteConnectionManager mRemoteConnectionManager =
            new RemoteConnectionManager(this);
    private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
    private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();

@@ -461,15 +461,9 @@ public abstract class ConnectionService extends Service {
        @Override
        public void onConferenceableConnectionsChanged(
                Connection connection, List<Connection> conferenceableConnections) {
            String id = mIdByConnection.get(connection);
            List<String> conferenceableCallIds = new ArrayList<>(conferenceableConnections.size());
            for (Connection c : conferenceableConnections) {
                if (mIdByConnection.containsKey(c)) {
                    conferenceableCallIds.add(mIdByConnection.get(c));
                }
            }
            Collections.sort(conferenceableCallIds);
            mAdapter.setConferenceableConnections(id, conferenceableCallIds);
            mAdapter.setConferenceableConnections(
                    mIdByConnection.get(connection),
                    createConnectionIdList(conferenceableConnections));
        }

        @Override
@@ -542,7 +536,8 @@ public abstract class ConnectionService extends Service {
                        connection.getAudioModeIsVoip(),
                        connection.getStatusHints(),
                        connection.getDisconnectCause(),
                        connection.getDisconnectMessage()));
                        connection.getDisconnectMessage(),
                        createConnectionIdList(connection.getConferenceableConnections())));
    }

    private void abort(String callId) {
@@ -716,6 +711,15 @@ public abstract class ConnectionService extends Service {
                connectionManagerPhoneAccount, request, false);
    }

    /**
     * Adds two {@code RemoteConnection}s to some {@code RemoteConference}.
     */
    public final void conferenceRemoteConnections(
            RemoteConnection a,
            RemoteConnection b) {
        mRemoteConnectionManager.conferenceRemoteConnections(a, b);
    }

    /**
     * Adds a new conference call. When a conference call is created either as a result of an
     * explicit request via {@link #onConference} or otherwise, the connection service should supply
@@ -824,11 +828,17 @@ public abstract class ConnectionService extends Service {

    /**
     * Notified that a connection has been removed from this connection service.
     * <p>
     * TODO: Deprecate this since we can listen to the Connection onDestroyed() to determine when
     * it is destroyed. This then percolates down to the RemoteConference stuff, where we can also
     * have a callback for one being added, but we don't need one for being destroyed.
     *
     * @param connection The connection which was removed.
     */
    public void onConnectionRemoved(Connection connection) {}

    public void onRemoteConferenceAdded(RemoteConference conference) {}

    /**
     * @hide
     */
@@ -836,6 +846,11 @@ public abstract class ConnectionService extends Service {
        return mIdByConference.containsKey(conference);
    }

    /** {@hide} */
    void addRemoteConference(RemoteConference remoteConference) {
        onRemoteConferenceAdded(remoteConference);
    }

    private void onAccountsInitialized() {
        mAreAccountsInitialized = true;
        for (Runnable r : mPreInitializationConnectionRequests) {
@@ -910,6 +925,17 @@ public abstract class ConnectionService extends Service {
        return getNullConference();
    }

    private List<String> createConnectionIdList(List<Connection> connections) {
        List<String> ids = new ArrayList<>();
        for (Connection c : connections) {
            if (mIdByConnection.containsKey(c)) {
                ids.add(mIdByConnection.get(c));
            }
        }
        Collections.sort(ids);
        return ids;
    }

    private Conference getNullConference() {
        if (sNullConference == null) {
            sNullConference = new Conference(null) {};
+30 −16
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ import android.os.Parcelable;

import com.android.internal.telecomm.IVideoProvider;

import java.util.ArrayList;
import java.util.List;

/**
 * Information about a connection that is used between Telecomm and the ConnectionService.
 * This is used to send initial Connection information to Telecomm when the connection is
@@ -29,20 +32,21 @@ import com.android.internal.telecomm.IVideoProvider;
 * @hide
 */
public final class ParcelableConnection implements Parcelable {
    private PhoneAccountHandle mPhoneAccount;
    private int mState;
    private int mCapabilities;
    private Uri mHandle;
    private int mHandlePresentation;
    private String mCallerDisplayName;
    private int mCallerDisplayNamePresentation;
    private IVideoProvider mVideoProvider;
    private int mVideoState;
    private boolean mRequestingRingback;
    private boolean mAudioModeIsVoip;
    private StatusHints mStatusHints;
    private int mDisconnectCause;
    private String mDisconnectMessage;
    private final PhoneAccountHandle mPhoneAccount;
    private final int mState;
    private final int mCapabilities;
    private final Uri mHandle;
    private final int mHandlePresentation;
    private final String mCallerDisplayName;
    private final int mCallerDisplayNamePresentation;
    private final IVideoProvider mVideoProvider;
    private final int mVideoState;
    private final boolean mRequestingRingback;
    private final boolean mAudioModeIsVoip;
    private final StatusHints mStatusHints;
    private final int mDisconnectCause;
    private final String mDisconnectMessage;
    private final List<String> mConferenceableConnectionIds;

    /** @hide */
    public ParcelableConnection(
@@ -59,7 +63,8 @@ public final class ParcelableConnection implements Parcelable {
            boolean audioModeIsVoip,
            StatusHints statusHints,
            int disconnectCause,
            String disconnectMessage) {
            String disconnectMessage,
            List<String> conferenceableConnectionIds) {
        mPhoneAccount = phoneAccount;
        mState = state;
        mCapabilities = capabilities;
@@ -74,6 +79,7 @@ public final class ParcelableConnection implements Parcelable {
        mStatusHints = statusHints;
        mDisconnectCause = disconnectCause;
        mDisconnectMessage = disconnectMessage;
        this.mConferenceableConnectionIds = conferenceableConnectionIds;
    }

    public PhoneAccountHandle getPhoneAccount() {
@@ -133,6 +139,10 @@ public final class ParcelableConnection implements Parcelable {
        return mDisconnectMessage;
    }

    public final List<String> getConferenceableConnectionIds() {
        return mConferenceableConnectionIds;
    }

    @Override
    public String toString() {
        return new StringBuilder()
@@ -166,6 +176,8 @@ public final class ParcelableConnection implements Parcelable {
            StatusHints statusHints = source.readParcelable(classLoader);
            int disconnectCauseCode = source.readInt();
            String disconnectCauseMessage = source.readString();
            List<String> conferenceableConnectionIds = new ArrayList<>();
            source.readStringList(conferenceableConnectionIds);

            return new ParcelableConnection(
                    phoneAccount,
@@ -181,7 +193,8 @@ public final class ParcelableConnection implements Parcelable {
                    audioModeIsVoip,
                    statusHints,
                    disconnectCauseCode,
                    disconnectCauseMessage);
                    disconnectCauseMessage,
                    conferenceableConnectionIds);
        }

        @Override
@@ -214,5 +227,6 @@ public final class ParcelableConnection implements Parcelable {
        destination.writeParcelable(mStatusHints, 0);
        destination.writeInt(mDisconnectCause);
        destination.writeString(mDisconnectMessage);
        destination.writeStringList(mConferenceableConnectionIds);
    }
}
+198 −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 com.android.internal.telecomm.IConnectionService;

import android.os.RemoteException;
import android.telephony.DisconnectCause;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Represents a conference call which can contain any number of {@link Connection} objects.
 */
public final class RemoteConference {

    public abstract static class Listener {
        public void onStateChanged(RemoteConference conference, int oldState, int newState) {}
        public void onDisconnected(RemoteConference conference, int cause, String message) {}
        public void onConnectionAdded(RemoteConference conference, RemoteConnection connection) {}
        public void onConnectionRemoved(RemoteConference conference, RemoteConnection connection) {}
        public void onCapabilitiesChanged(RemoteConference conference, int capabilities) {}
        public void onDestroyed(RemoteConference conference) {}
    }

    private final String mId;
    private final IConnectionService mConnectionService;

    private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
    private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
    private final List<RemoteConnection> mUnmodifiableChildConnections =
            Collections.unmodifiableList(mChildConnections);

    private int mState = Connection.STATE_NEW;
    private int mDisconnectCause = DisconnectCause.NOT_VALID;
    private int mCallCapabilities;
    private String mDisconnectMessage;

    /** {@hide} */
    RemoteConference(String id, IConnectionService connectionService) {
        mId = id;
        mConnectionService = connectionService;
    }

    /** {@hide} */
    String getId() {
        return mId;
    }

    /** {@hide} */
    void setDestroyed() {
        for (RemoteConnection connection : mChildConnections) {
            connection.setConference(null);
        }
        for (Listener l : mListeners) {
            l.onDestroyed(this);
        }
    }

    /** {@hide} */
    void setState(int newState) {
        if (newState != Connection.STATE_ACTIVE &&
                newState != Connection.STATE_HOLDING &&
                newState != Connection.STATE_DISCONNECTED) {
            Log.w(this, "Unsupported state transition for Conference call.",
                    Connection.stateToString(newState));
            return;
        }

        if (mState != newState) {
            int oldState = mState;
            mState = newState;
            for (Listener l : mListeners) {
                l.onStateChanged(this, oldState, newState);
            }
        }
    }

    /** {@hide} */
    void addConnection(RemoteConnection connection) {
        if (!mChildConnections.contains(connection)) {
            mChildConnections.add(connection);
            connection.setConference(this);
            for (Listener l : mListeners) {
                l.onConnectionAdded(this, connection);
            }
        }
    }

    /** {@hide} */
    void removeConnection(RemoteConnection connection) {
        if (mChildConnections.contains(connection)) {
            mChildConnections.remove(connection);
            connection.setConference(null);
            for (Listener l : mListeners) {
                l.onConnectionRemoved(this, connection);
            }
        }
    }

    /** {@hide} */
    void setCallCapabilities(int capabilities) {
        if (mCallCapabilities != capabilities) {
            mCallCapabilities = capabilities;
            for (Listener l : mListeners) {
                l.onCapabilitiesChanged(this, mCallCapabilities);
            }
        }
    }

    /** {@hide} */
    void setDisconnected(int cause, String message) {
        if (mState != Connection.STATE_DISCONNECTED) {
            mDisconnectCause = cause;
            mDisconnectMessage = message;
            setState(Connection.STATE_DISCONNECTED);
            for (Listener l : mListeners) {
                l.onDisconnected(this, cause, message);
            }
        }
    }

    public final List<RemoteConnection> getConnections() {
        return mUnmodifiableChildConnections;
    }

    public final int getState() {
        return mState;
    }

    public final int getCallCapabilities() {
        return mCallCapabilities;
    }

    public void disconnect() {
        try {
            mConnectionService.disconnect(mId);
        } catch (RemoteException e) {
        }
    }

    public void separate(RemoteConnection connection) {
        if (mChildConnections.contains(connection)) {
            try {
                mConnectionService.splitFromConference(connection.getId());
            } catch (RemoteException e) {
            }
        }
    }

    public void hold() {
        try {
            mConnectionService.hold(mId);
        } catch (RemoteException e) {
        }
    }

    public void unhold() {
        try {
            mConnectionService.unhold(mId);
        } catch (RemoteException e) {
        }
    }

    public int getDisconnectCause() {
        return mDisconnectCause;
    }

    public String getDisconnectMessage() {
        return mDisconnectMessage;
    }

    public final void addListener(Listener listener) {
        mListeners.add(listener);
    }

    public final void removeListener(Listener listener) {
        mListeners.remove(listener);
    }
}
Loading