blob: 9b350c1978a290a9cdc227f54e300a5bf9b12436 [file] [log] [blame]
Santos Cordon823fd3c2014-08-07 18:35:18 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Santos Cordon823fd3c2014-08-07 18:35:18 -070018
Santos Cordon823fd3c2014-08-07 18:35:18 -070019import java.util.Collections;
Santos Cordon823fd3c2014-08-07 18:35:18 -070020import java.util.List;
21import java.util.Set;
22import java.util.concurrent.CopyOnWriteArrayList;
23import java.util.concurrent.CopyOnWriteArraySet;
24
25/**
26 * Represents a conference call which can contain any number of {@link Connection} objects.
27 */
28public abstract class Conference {
29
30 /** @hide */
31 public abstract static class Listener {
32 public void onStateChanged(Conference conference, int oldState, int newState) {}
Andrew Lee7f3d41f2014-09-11 17:33:16 -070033 public void onDisconnected(Conference conference, DisconnectCause disconnectCause) {}
Santos Cordon823fd3c2014-08-07 18:35:18 -070034 public void onConnectionAdded(Conference conference, Connection connection) {}
35 public void onConnectionRemoved(Conference conference, Connection connection) {}
36 public void onDestroyed(Conference conference) {}
37 public void onCapabilitiesChanged(Conference conference, int capabilities) {}
38 }
39
40 private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
41 private final List<Connection> mChildConnections = new CopyOnWriteArrayList<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -070042 private final List<Connection> mUnmodifiableChildConnections =
Santos Cordon823fd3c2014-08-07 18:35:18 -070043 Collections.unmodifiableList(mChildConnections);
44
45 private PhoneAccountHandle mPhoneAccount;
Yorke Leea0d3ca92014-09-15 19:18:13 -070046 private AudioState mAudioState;
Santos Cordon823fd3c2014-08-07 18:35:18 -070047 private int mState = Connection.STATE_NEW;
Andrew Lee7f3d41f2014-09-11 17:33:16 -070048 private DisconnectCause mDisconnectCause;
Santos Cordon823fd3c2014-08-07 18:35:18 -070049 private int mCapabilities;
50 private String mDisconnectMessage;
51
Nancy Chen56fc25d2014-09-09 12:24:51 -070052 /**
53 * Constructs a new Conference with a mandatory {@link PhoneAccountHandle}
54 *
55 * @param phoneAccount The {@code PhoneAccountHandle} associated with the conference.
56 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070057 public Conference(PhoneAccountHandle phoneAccount) {
58 mPhoneAccount = phoneAccount;
59 }
60
Nancy Chen56fc25d2014-09-09 12:24:51 -070061 /**
62 * Returns the {@link PhoneAccountHandle} the conference call is being placed through.
63 *
64 * @return A {@code PhoneAccountHandle} object representing the PhoneAccount of the conference.
65 */
Nancy Chenea38cca2014-09-05 16:38:49 -070066 public final PhoneAccountHandle getPhoneAccountHandle() {
Santos Cordon823fd3c2014-08-07 18:35:18 -070067 return mPhoneAccount;
68 }
69
Nancy Chen56fc25d2014-09-09 12:24:51 -070070 /**
71 * Returns the list of connections currently associated with the conference call.
72 *
73 * @return A list of {@code Connection} objects which represent the children of the conference.
74 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070075 public final List<Connection> getConnections() {
Ihab Awadb8e85c72014-08-23 20:34:57 -070076 return mUnmodifiableChildConnections;
Santos Cordon823fd3c2014-08-07 18:35:18 -070077 }
78
Nancy Chen56fc25d2014-09-09 12:24:51 -070079 /**
80 * Gets the state of the conference call. See {@link Connection} for valid values.
81 *
82 * @return A constant representing the state the conference call is currently in.
83 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070084 public final int getState() {
85 return mState;
86 }
87
Nancy Chen56fc25d2014-09-09 12:24:51 -070088 /**
89 * Returns the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
90 *
91 * @return A bitmask of the {@code PhoneCapabilities} of the conference call.
92 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070093 public final int getCapabilities() {
94 return mCapabilities;
95 }
96
97 /**
Yorke Leea0d3ca92014-09-15 19:18:13 -070098 * @return The audio state of the conference, describing how its audio is currently
99 * being routed by the system. This is {@code null} if this Conference
100 * does not directly know about its audio state.
101 */
102 public final AudioState getAudioState() {
103 return mAudioState;
104 }
105
106 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -0700107 * Invoked when the Conference and all it's {@link Connection}s should be disconnected.
108 */
109 public void onDisconnect() {}
110
111 /**
112 * Invoked when the specified {@link Connection} should be separated from the conference call.
113 *
114 * @param connection The connection to separate.
115 */
116 public void onSeparate(Connection connection) {}
117
118 /**
119 * Invoked when the conference should be put on hold.
120 */
121 public void onHold() {}
122
123 /**
124 * Invoked when the conference should be moved from hold to active.
125 */
126 public void onUnhold() {}
127
128 /**
Santos Cordona4868042014-09-04 17:39:22 -0700129 * Invoked when the child calls should be merged. Only invoked if the conference contains the
130 * capability {@link PhoneCapabilities#MERGE_CONFERENCE}.
131 */
132 public void onMerge() {}
133
134 /**
135 * Invoked when the child calls should be swapped. Only invoked if the conference contains the
136 * capability {@link PhoneCapabilities#SWAP_CONFERENCE}.
137 */
138 public void onSwap() {}
139
140 /**
Yorke Leea0d3ca92014-09-15 19:18:13 -0700141 * Notifies this conference of a request to play a DTMF tone.
142 *
143 * @param c A DTMF character.
144 */
145 public void onPlayDtmfTone(char c) {}
146
147 /**
148 * Notifies this conference of a request to stop any currently playing DTMF tones.
149 */
150 public void onStopDtmfTone() {}
151
152 /**
153 * Notifies this conference that the {@link #getAudioState()} property has a new value.
154 *
155 * @param state The new call audio state.
156 */
157 public void onAudioStateChanged(AudioState state) {}
158
159 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -0700160 * Sets state to be on hold.
161 */
162 public final void setOnHold() {
163 setState(Connection.STATE_HOLDING);
164 }
165
166 /**
167 * Sets state to be active.
168 */
169 public final void setActive() {
170 setState(Connection.STATE_ACTIVE);
171 }
172
173 /**
174 * Sets state to disconnected.
175 *
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700176 * @param disconnectCause The reason for the disconnection, as described by
177 * {@link android.telecom.DisconnectCause}.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700178 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700179 public final void setDisconnected(DisconnectCause disconnectCause) {
180 mDisconnectCause = disconnectCause;;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700181 setState(Connection.STATE_DISCONNECTED);
182 for (Listener l : mListeners) {
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700183 l.onDisconnected(this, mDisconnectCause);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700184 }
185 }
186
187 /**
Nancy Chen56fc25d2014-09-09 12:24:51 -0700188 * Sets the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
189 *
190 * @param capabilities A bitmask of the {@code PhoneCapabilities} of the conference call.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700191 */
192 public final void setCapabilities(int capabilities) {
193 if (capabilities != mCapabilities) {
194 mCapabilities = capabilities;
195
196 for (Listener l : mListeners) {
197 l.onCapabilitiesChanged(this, mCapabilities);
198 }
199 }
200 }
201
202 /**
203 * Adds the specified connection as a child of this conference.
204 *
205 * @param connection The connection to add.
206 * @return True if the connection was successfully added.
207 */
Santos Cordona4868042014-09-04 17:39:22 -0700208 public final boolean addConnection(Connection connection) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700209 if (connection != null && !mChildConnections.contains(connection)) {
210 if (connection.setConference(this)) {
211 mChildConnections.add(connection);
212 for (Listener l : mListeners) {
213 l.onConnectionAdded(this, connection);
214 }
215 return true;
216 }
217 }
218 return false;
219 }
220
221 /**
222 * Removes the specified connection as a child of this conference.
223 *
224 * @param connection The connection to remove.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700225 */
Santos Cordona4868042014-09-04 17:39:22 -0700226 public final void removeConnection(Connection connection) {
Santos Cordon0159ac02014-08-21 14:28:11 -0700227 Log.d(this, "removing %s from %s", connection, mChildConnections);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700228 if (connection != null && mChildConnections.remove(connection)) {
229 connection.resetConference();
230 for (Listener l : mListeners) {
231 l.onConnectionRemoved(this, connection);
232 }
233 }
234 }
235
236 /**
Nancy Chenea38cca2014-09-05 16:38:49 -0700237 * Tears down the conference object and any of its current connections.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700238 */
Santos Cordona4868042014-09-04 17:39:22 -0700239 public final void destroy() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700240 Log.d(this, "destroying conference : %s", this);
241 // Tear down the children.
Santos Cordon0159ac02014-08-21 14:28:11 -0700242 for (Connection connection : mChildConnections) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700243 Log.d(this, "removing connection %s", connection);
244 removeConnection(connection);
245 }
246
247 // If not yet disconnected, set the conference call as disconnected first.
248 if (mState != Connection.STATE_DISCONNECTED) {
249 Log.d(this, "setting to disconnected");
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700250 setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
Santos Cordon823fd3c2014-08-07 18:35:18 -0700251 }
252
253 // ...and notify.
254 for (Listener l : mListeners) {
255 l.onDestroyed(this);
256 }
257 }
258
259 /**
260 * Add a listener to be notified of a state change.
261 *
262 * @param listener The new listener.
263 * @return This conference.
264 * @hide
265 */
266 public final Conference addListener(Listener listener) {
267 mListeners.add(listener);
268 return this;
269 }
270
271 /**
272 * Removes the specified listener.
273 *
274 * @param listener The listener to remove.
275 * @return This conference.
276 * @hide
277 */
278 public final Conference removeListener(Listener listener) {
279 mListeners.remove(listener);
280 return this;
281 }
282
Yorke Leea0d3ca92014-09-15 19:18:13 -0700283 /**
284 * Inform this Conference that the state of its audio output has been changed externally.
285 *
286 * @param state The new audio state.
287 * @hide
288 */
289 final void setAudioState(AudioState state) {
290 Log.d(this, "setAudioState %s", state);
291 mAudioState = state;
292 onAudioStateChanged(state);
293 }
294
Santos Cordon823fd3c2014-08-07 18:35:18 -0700295 private void setState(int newState) {
296 if (newState != Connection.STATE_ACTIVE &&
297 newState != Connection.STATE_HOLDING &&
298 newState != Connection.STATE_DISCONNECTED) {
299 Log.w(this, "Unsupported state transition for Conference call.",
300 Connection.stateToString(newState));
301 return;
302 }
303
304 if (mState != newState) {
305 int oldState = mState;
306 mState = newState;
307 for (Listener l : mListeners) {
308 l.onStateChanged(this, oldState, newState);
309 }
310 }
311 }
312}