am d4340f89: Merge "Change Connections to allow setting conferenceable with conferences." into lmp-mr1-dev

automerge: ce5a8e8

* commit 'ce5a8e861d16814e1d452f4512f05b258b95de1d':
  Change Connections to allow setting conferenceable with conferences.
This commit is contained in:
Tyler Gunn
2014-11-20 21:20:30 +00:00
committed by android-build-merger
4 changed files with 146 additions and 25 deletions

View File

@@ -30,7 +30,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
* @hide * @hide
*/ */
@SystemApi @SystemApi
public abstract class Conference { public abstract class Conference implements IConferenceable {
/** @hide */ /** @hide */
public abstract static class Listener { public abstract static class Listener {

View File

@@ -47,7 +47,7 @@ import java.util.concurrent.ConcurrentHashMap;
* @hide * @hide
*/ */
@SystemApi @SystemApi
public abstract class Connection { public abstract class Connection implements IConferenceable {
public static final int STATE_INITIALIZING = 0; public static final int STATE_INITIALIZING = 0;
@@ -82,8 +82,8 @@ public abstract class Connection {
Connection c, VideoProvider videoProvider) {} Connection c, VideoProvider videoProvider) {}
public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {} public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
public void onStatusHintsChanged(Connection c, StatusHints statusHints) {} public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
public void onConferenceableConnectionsChanged( public void onConferenceablesChanged(
Connection c, List<Connection> conferenceableConnections) {} Connection c, List<IConferenceable> conferenceables) {}
public void onConferenceChanged(Connection c, Conference conference) {} public void onConferenceChanged(Connection c, Conference conference) {}
/** @hide */ /** @hide */
public void onConferenceParticipantsChanged(Connection c, public void onConferenceParticipantsChanged(Connection c,
@@ -449,7 +449,16 @@ public abstract class Connection {
private final Listener mConnectionDeathListener = new Listener() { private final Listener mConnectionDeathListener = new Listener() {
@Override @Override
public void onDestroyed(Connection c) { 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(); fireOnConferenceableConnectionsChanged();
} }
} }
@@ -462,9 +471,9 @@ public abstract class Connection {
*/ */
private final Set<Listener> mListeners = Collections.newSetFromMap( private final Set<Listener> mListeners = Collections.newSetFromMap(
new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
private final List<Connection> mConferenceableConnections = new ArrayList<>(); private final List<IConferenceable> mConferenceables = new ArrayList<>();
private final List<Connection> mUnmodifiableConferenceableConnections = private final List<IConferenceable> mUnmodifiableConferenceables =
Collections.unmodifiableList(mConferenceableConnections); Collections.unmodifiableList(mConferenceables);
private int mState = STATE_NEW; private int mState = STATE_NEW;
private AudioState mAudioState; private AudioState mAudioState;
@@ -864,19 +873,44 @@ public abstract class Connection {
for (Connection c : conferenceableConnections) { for (Connection c : conferenceableConnections) {
// If statement checks for duplicates in input. It makes it N^2 but we're dealing with a // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a
// small amount of items here. // small amount of items here.
if (!mConferenceableConnections.contains(c)) { if (!mConferenceables.contains(c)) {
c.addConnectionListener(mConnectionDeathListener); c.addConnectionListener(mConnectionDeathListener);
mConferenceableConnections.add(c); mConferenceables.add(c);
} }
} }
fireOnConferenceableConnectionsChanged(); 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() { public final void setConferenceables(List<IConferenceable> conferenceables) {
return mUnmodifiableConferenceableConnections; 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() { private final void fireOnConferenceableConnectionsChanged() {
for (Listener l : mListeners) { for (Listener l : mListeners) {
l.onConferenceableConnectionsChanged(this, getConferenceableConnections()); l.onConferenceablesChanged(this, getConferenceables());
} }
} }
@@ -1120,10 +1154,16 @@ public abstract class Connection {
} }
private final void clearConferenceableList() { private final void clearConferenceableList() {
for (Connection c : mConferenceableConnections) { for (IConferenceable c : mConferenceables) {
c.removeConnectionListener(mConnectionDeathListener); 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();
} }
/** /**

View File

@@ -515,11 +515,11 @@ public abstract class ConnectionService extends Service {
} }
@Override @Override
public void onConferenceableConnectionsChanged( public void onConferenceablesChanged(
Connection connection, List<Connection> conferenceableConnections) { Connection connection, List<IConferenceable> conferenceables) {
mAdapter.setConferenceableConnections( mAdapter.setConferenceableConnections(
mIdByConnection.get(connection), mIdByConnection.get(connection),
createConnectionIdList(conferenceableConnections)); createIdList(conferenceables));
} }
@Override @Override
@@ -602,7 +602,7 @@ public abstract class ConnectionService extends Service {
connection.getAudioModeIsVoip(), connection.getAudioModeIsVoip(),
connection.getStatusHints(), connection.getStatusHints(),
connection.getDisconnectCause(), connection.getDisconnectCause(),
createConnectionIdList(connection.getConferenceableConnections()))); createIdList(connection.getConferenceables())));
} }
private void abort(String callId) { private void abort(String callId) {
@@ -682,12 +682,19 @@ public abstract class ConnectionService extends Service {
private void conference(String callId1, String callId2) { private void conference(String callId1, String callId2) {
Log.d(this, "conference %s, %s", callId1, callId2); Log.d(this, "conference %s, %s", callId1, callId2);
// Attempt to get second connection or conference.
Connection connection2 = findConnectionForAction(callId2, "conference"); Connection connection2 = findConnectionForAction(callId2, "conference");
Conference conference2 = getNullConference();
if (connection2 == getNullConnection()) { if (connection2 == getNullConnection()) {
Log.w(this, "Connection2 missing in conference request %s.", callId2); conference2 = findConferenceForAction(callId2, "conference");
if (conference2 == getNullConference()) {
Log.w(this, "Connection2 or Conference2 missing in conference request %s.",
callId2);
return; return;
} }
}
// Attempt to get first connection or conference and perform merge.
Connection connection1 = findConnectionForAction(callId1, "conference"); Connection connection1 = findConnectionForAction(callId1, "conference");
if (connection1 == getNullConnection()) { if (connection1 == getNullConnection()) {
Conference conference1 = findConferenceForAction(callId1, "addConnection"); Conference conference1 = findConferenceForAction(callId1, "addConnection");
@@ -696,12 +703,28 @@ public abstract class ConnectionService extends Service {
"Connection1 or Conference1 missing in conference request %s.", "Connection1 or Conference1 missing in conference request %s.",
callId1); callId1);
} else { } else {
// Call 1 is a conference.
if (connection2 != getNullConnection()) {
// Call 2 is a connection so merge via call 1 (conference).
conference1.onMerge(connection2); 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 { } else {
// 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); onConference(connection1, connection2);
} }
} }
}
private void splitFromConference(String callId) { private void splitFromConference(String callId) {
Log.d(this, "splitFromConference(%s)", callId); Log.d(this, "splitFromConference(%s)", callId);
@@ -1111,6 +1134,33 @@ public abstract class ConnectionService extends Service {
return ids; 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() { private Conference getNullConference() {
if (sNullConference == null) { if (sNullConference == null) {
sNullConference = new Conference(null) {}; sNullConference = new Conference(null) {};

View File

@@ -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 {
}