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:
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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) {};
|
||||||
|
|||||||
31
telecomm/java/android/telecom/IConferenceable.java
Normal file
31
telecomm/java/android/telecom/IConferenceable.java
Normal 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 {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user