diff options
| author | 2014-11-17 15:49:51 -0800 | |
|---|---|---|
| committer | 2014-11-17 15:49:51 -0800 | |
| commit | 6d76ca0438c2cb7a7d5d91992db819c063c0a57b (patch) | |
| tree | 74a11f2f8b5c7d736a3ff816c31d9a998f21cada | |
| parent | 5aadd5b6fa8ee9f09cd4870c8f104c1e611aebcd (diff) | |
Change Connections to allow setting conferenceable with conferences.
- Added IConferenceable interface used so that connections and conferences
can both be considered candidates as "conferenceable" with a connection.
- Fixed ConnectionService#conference to support cases where either call 1
or call 2 is a conference and the other is a connection.  Previously did
not support cases where call 2 is a conference.
Bug: 18200934
Change-Id: I32a8dd30a154d6280f2ae89fd147817235998465
| -rw-r--r-- | telecomm/java/android/telecom/Conference.java | 2 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/Connection.java | 72 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/ConnectionService.java | 66 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/IConferenceable.java | 31 | 
4 files changed, 146 insertions, 25 deletions
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index 215c68242856..6e404deb2619 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -30,7 +30,7 @@ import java.util.concurrent.CopyOnWriteArraySet;   * @hide   */  @SystemApi -public abstract class Conference { +public abstract class Conference implements IConferenceable {      /** @hide */      public abstract static class Listener { diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 63b44a6fa942..fb63c852131d 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -47,7 +47,7 @@ import java.util.concurrent.ConcurrentHashMap;   * @hide   */  @SystemApi -public abstract class Connection { +public abstract class Connection implements IConferenceable {      public static final int STATE_INITIALIZING = 0; @@ -82,8 +82,8 @@ public abstract class Connection {                  Connection c, VideoProvider videoProvider) {}          public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}          public void onStatusHintsChanged(Connection c, StatusHints statusHints) {} -        public void onConferenceableConnectionsChanged( -                Connection c, List<Connection> conferenceableConnections) {} +        public void onConferenceablesChanged( +                Connection c, List<IConferenceable> conferenceables) {}          public void onConferenceChanged(Connection c, Conference conference) {}          /** @hide */          public void onConferenceParticipantsChanged(Connection c, @@ -449,7 +449,16 @@ public abstract class Connection {      private final Listener mConnectionDeathListener = new Listener() {          @Override          public void onDestroyed(Connection c) { -            if (mConferenceableConnections.remove(c)) { +            if (mConferenceables.remove(c)) { +                fireOnConferenceableConnectionsChanged(); +            } +        } +    }; + +    private final Conference.Listener mConferenceDeathListener = new Conference.Listener() { +        @Override +        public void onDestroyed(Conference c) { +            if (mConferenceables.remove(c)) {                  fireOnConferenceableConnectionsChanged();              }          } @@ -462,9 +471,9 @@ public abstract class Connection {       */      private final Set<Listener> mListeners = Collections.newSetFromMap(              new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); -    private final List<Connection> mConferenceableConnections = new ArrayList<>(); -    private final List<Connection> mUnmodifiableConferenceableConnections = -            Collections.unmodifiableList(mConferenceableConnections); +    private final List<IConferenceable> mConferenceables = new ArrayList<>(); +    private final List<IConferenceable> mUnmodifiableConferenceables = +            Collections.unmodifiableList(mConferenceables);      private int mState = STATE_NEW;      private AudioState mAudioState; @@ -864,19 +873,44 @@ public abstract class Connection {          for (Connection c : conferenceableConnections) {              // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a              // small amount of items here. -            if (!mConferenceableConnections.contains(c)) { +            if (!mConferenceables.contains(c)) {                  c.addConnectionListener(mConnectionDeathListener); -                mConferenceableConnections.add(c); +                mConferenceables.add(c);              }          }          fireOnConferenceableConnectionsChanged();      }      /** -     * Returns the connections with which this connection can be conferenced. +     * Similar to {@link #setConferenceableConnections(java.util.List)}, sets a list of connections +     * or conferences with which this connection can be conferenced. +     * +     * @param conferenceables The conferenceables.       */ -    public final List<Connection> getConferenceableConnections() { -        return mUnmodifiableConferenceableConnections; +    public final void setConferenceables(List<IConferenceable> conferenceables) { +        clearConferenceableList(); +        for (IConferenceable c : conferenceables) { +            // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a +            // small amount of items here. +            if (!mConferenceables.contains(c)) { +                if (c instanceof Connection) { +                    Connection connection = (Connection) c; +                    connection.addConnectionListener(mConnectionDeathListener); +                } else if (c instanceof Conference) { +                    Conference conference = (Conference) c; +                    conference.addListener(mConferenceDeathListener); +                } +                mConferenceables.add(c); +            } +        } +        fireOnConferenceableConnectionsChanged(); +    } + +    /** +     * Returns the connections or conferences with which this connection can be conferenced. +     */ +    public final List<IConferenceable> getConferenceables() { +        return mUnmodifiableConferenceables;      }      /* @@ -1109,7 +1143,7 @@ public abstract class Connection {      private final void  fireOnConferenceableConnectionsChanged() {          for (Listener l : mListeners) { -            l.onConferenceableConnectionsChanged(this, getConferenceableConnections()); +            l.onConferenceablesChanged(this, getConferenceables());          }      } @@ -1120,10 +1154,16 @@ public abstract class Connection {      }      private final void clearConferenceableList() { -        for (Connection c : mConferenceableConnections) { -            c.removeConnectionListener(mConnectionDeathListener); +        for (IConferenceable c : mConferenceables) { +            if (c instanceof Connection) { +                Connection connection = (Connection) c; +                connection.removeConnectionListener(mConnectionDeathListener); +            } else if (c instanceof Conference) { +                Conference conference = (Conference) c; +                conference.removeListener(mConferenceDeathListener); +            }          } -        mConferenceableConnections.clear(); +        mConferenceables.clear();      }      /** diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 48e6ff3d02ee..08f385378450 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -515,11 +515,11 @@ public abstract class ConnectionService extends Service {          }          @Override -        public void onConferenceableConnectionsChanged( -                Connection connection, List<Connection> conferenceableConnections) { +        public void onConferenceablesChanged( +                Connection connection, List<IConferenceable> conferenceables) {              mAdapter.setConferenceableConnections(                      mIdByConnection.get(connection), -                    createConnectionIdList(conferenceableConnections)); +                    createIdList(conferenceables));          }          @Override @@ -602,7 +602,7 @@ public abstract class ConnectionService extends Service {                          connection.getAudioModeIsVoip(),                          connection.getStatusHints(),                          connection.getDisconnectCause(), -                        createConnectionIdList(connection.getConferenceableConnections()))); +                        createIdList(connection.getConferenceables())));      }      private void abort(String callId) { @@ -682,12 +682,19 @@ public abstract class ConnectionService extends Service {      private void conference(String callId1, String callId2) {          Log.d(this, "conference %s, %s", callId1, callId2); +        // Attempt to get second connection or conference.          Connection connection2 = findConnectionForAction(callId2, "conference"); +        Conference conference2 = getNullConference();          if (connection2 == getNullConnection()) { -            Log.w(this, "Connection2 missing in conference request %s.", callId2); -            return; +            conference2 = findConferenceForAction(callId2, "conference"); +            if (conference2 == getNullConference()) { +                Log.w(this, "Connection2 or Conference2 missing in conference request %s.", +                        callId2); +                return; +            }          } +        // Attempt to get first connection or conference and perform merge.          Connection connection1 = findConnectionForAction(callId1, "conference");          if (connection1 == getNullConnection()) {              Conference conference1 = findConferenceForAction(callId1, "addConnection"); @@ -696,10 +703,26 @@ public abstract class ConnectionService extends Service {                          "Connection1 or Conference1 missing in conference request %s.",                          callId1);              } else { -                conference1.onMerge(connection2); +                // Call 1 is a conference. +                if (connection2 != getNullConnection()) { +                    // Call 2 is a connection so merge via call 1 (conference). +                    conference1.onMerge(connection2); +                } else { +                    // Call 2 is ALSO a conference; this should never happen. +                    Log.wtf(this, "There can only be one conference and an attempt was made to " + +                            "merge two conferences."); +                    return; +                }              }          } else { -            onConference(connection1, connection2); +            // Call 1 is a connection. +            if (conference2 != getNullConference()) { +                // Call 2 is a conference, so merge via call 2. +                conference2.onMerge(connection1); +            } else { +                // Call 2 is a connection, so merge together. +                onConference(connection1, connection2); +            }          }      } @@ -1111,6 +1134,33 @@ public abstract class ConnectionService extends Service {          return ids;      } +    /** +     * Builds a list of {@link Connection} and {@link Conference} IDs based on the list of +     * {@link IConferenceable}s passed in. +     * +     * @param conferenceables The {@link IConferenceable} connections and conferences. +     * @return List of string conference and call Ids. +     */ +    private List<String> createIdList(List<IConferenceable> conferenceables) { +        List<String> ids = new ArrayList<>(); +        for (IConferenceable c : conferenceables) { +            // Only allow Connection and Conference conferenceables. +            if (c instanceof Connection) { +                Connection connection = (Connection) c; +                if (mIdByConnection.containsKey(connection)) { +                    ids.add(mIdByConnection.get(connection)); +                } +            } else if (c instanceof Conference) { +                Conference conference = (Conference) c; +                if (mIdByConference.containsKey(conference)) { +                    ids.add(mIdByConference.get(conference)); +                } +            } +        } +        Collections.sort(ids); +        return ids; +    } +      private Conference getNullConference() {          if (sNullConference == null) {              sNullConference = new Conference(null) {}; diff --git a/telecomm/java/android/telecom/IConferenceable.java b/telecomm/java/android/telecom/IConferenceable.java new file mode 100644 index 000000000000..095d7cbac545 --- /dev/null +++ b/telecomm/java/android/telecom/IConferenceable.java @@ -0,0 +1,31 @@ +/* + * 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.telecom; + +import android.annotation.SystemApi; + +/** + * Interface used to identify entities with which another entity can participate in a conference + * call with.  The {@link ConnectionService} implementation will only recognize + * {@link IConferenceable}s which are {@link Connection}s or {@link Conference}s. + * + * @hide + */ +@SystemApi +public interface IConferenceable { + +}  |