blob: e47d9d160cb1712080ae704fd453ad8b5c3beb38 [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
Tyler Gunn711d876fd2014-09-19 11:17:02 -070019import android.annotation.SystemApi;
20
Santos Cordon823fd3c2014-08-07 18:35:18 -070021import java.util.Collections;
Santos Cordon823fd3c2014-08-07 18:35:18 -070022import java.util.List;
23import java.util.Set;
24import java.util.concurrent.CopyOnWriteArrayList;
25import java.util.concurrent.CopyOnWriteArraySet;
26
27/**
28 * Represents a conference call which can contain any number of {@link Connection} objects.
Tyler Gunn711d876fd2014-09-19 11:17:02 -070029 * @hide
Santos Cordon823fd3c2014-08-07 18:35:18 -070030 */
Tyler Gunn711d876fd2014-09-19 11:17:02 -070031@SystemApi
Santos Cordon823fd3c2014-08-07 18:35:18 -070032public abstract class Conference {
33
34 /** @hide */
35 public abstract static class Listener {
36 public void onStateChanged(Conference conference, int oldState, int newState) {}
Andrew Lee7f3d41f2014-09-11 17:33:16 -070037 public void onDisconnected(Conference conference, DisconnectCause disconnectCause) {}
Santos Cordon823fd3c2014-08-07 18:35:18 -070038 public void onConnectionAdded(Conference conference, Connection connection) {}
39 public void onConnectionRemoved(Conference conference, Connection connection) {}
40 public void onDestroyed(Conference conference) {}
41 public void onCapabilitiesChanged(Conference conference, int capabilities) {}
42 }
43
44 private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
45 private final List<Connection> mChildConnections = new CopyOnWriteArrayList<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -070046 private final List<Connection> mUnmodifiableChildConnections =
Santos Cordon823fd3c2014-08-07 18:35:18 -070047 Collections.unmodifiableList(mChildConnections);
48
49 private PhoneAccountHandle mPhoneAccount;
Yorke Leea0d3ca92014-09-15 19:18:13 -070050 private AudioState mAudioState;
Santos Cordon823fd3c2014-08-07 18:35:18 -070051 private int mState = Connection.STATE_NEW;
Andrew Lee7f3d41f2014-09-11 17:33:16 -070052 private DisconnectCause mDisconnectCause;
Santos Cordon823fd3c2014-08-07 18:35:18 -070053 private int mCapabilities;
54 private String mDisconnectMessage;
55
Nancy Chen56fc25d2014-09-09 12:24:51 -070056 /**
57 * Constructs a new Conference with a mandatory {@link PhoneAccountHandle}
58 *
59 * @param phoneAccount The {@code PhoneAccountHandle} associated with the conference.
60 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070061 public Conference(PhoneAccountHandle phoneAccount) {
62 mPhoneAccount = phoneAccount;
63 }
64
Nancy Chen56fc25d2014-09-09 12:24:51 -070065 /**
66 * Returns the {@link PhoneAccountHandle} the conference call is being placed through.
67 *
68 * @return A {@code PhoneAccountHandle} object representing the PhoneAccount of the conference.
69 */
Nancy Chenea38cca2014-09-05 16:38:49 -070070 public final PhoneAccountHandle getPhoneAccountHandle() {
Santos Cordon823fd3c2014-08-07 18:35:18 -070071 return mPhoneAccount;
72 }
73
Nancy Chen56fc25d2014-09-09 12:24:51 -070074 /**
75 * Returns the list of connections currently associated with the conference call.
76 *
77 * @return A list of {@code Connection} objects which represent the children of the conference.
78 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070079 public final List<Connection> getConnections() {
Ihab Awadb8e85c72014-08-23 20:34:57 -070080 return mUnmodifiableChildConnections;
Santos Cordon823fd3c2014-08-07 18:35:18 -070081 }
82
Nancy Chen56fc25d2014-09-09 12:24:51 -070083 /**
84 * Gets the state of the conference call. See {@link Connection} for valid values.
85 *
86 * @return A constant representing the state the conference call is currently in.
87 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070088 public final int getState() {
89 return mState;
90 }
91
Nancy Chen56fc25d2014-09-09 12:24:51 -070092 /**
93 * Returns the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
94 *
95 * @return A bitmask of the {@code PhoneCapabilities} of the conference call.
96 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070097 public final int getCapabilities() {
98 return mCapabilities;
99 }
100
101 /**
Yorke Leea0d3ca92014-09-15 19:18:13 -0700102 * @return The audio state of the conference, describing how its audio is currently
103 * being routed by the system. This is {@code null} if this Conference
104 * does not directly know about its audio state.
105 */
106 public final AudioState getAudioState() {
107 return mAudioState;
108 }
109
110 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -0700111 * Invoked when the Conference and all it's {@link Connection}s should be disconnected.
112 */
113 public void onDisconnect() {}
114
115 /**
116 * Invoked when the specified {@link Connection} should be separated from the conference call.
117 *
118 * @param connection The connection to separate.
119 */
120 public void onSeparate(Connection connection) {}
121
122 /**
123 * Invoked when the conference should be put on hold.
124 */
125 public void onHold() {}
126
127 /**
128 * Invoked when the conference should be moved from hold to active.
129 */
130 public void onUnhold() {}
131
132 /**
Santos Cordona4868042014-09-04 17:39:22 -0700133 * Invoked when the child calls should be merged. Only invoked if the conference contains the
134 * capability {@link PhoneCapabilities#MERGE_CONFERENCE}.
135 */
136 public void onMerge() {}
137
138 /**
139 * Invoked when the child calls should be swapped. Only invoked if the conference contains the
140 * capability {@link PhoneCapabilities#SWAP_CONFERENCE}.
141 */
142 public void onSwap() {}
143
144 /**
Yorke Leea0d3ca92014-09-15 19:18:13 -0700145 * Notifies this conference of a request to play a DTMF tone.
146 *
147 * @param c A DTMF character.
148 */
149 public void onPlayDtmfTone(char c) {}
150
151 /**
152 * Notifies this conference of a request to stop any currently playing DTMF tones.
153 */
154 public void onStopDtmfTone() {}
155
156 /**
157 * Notifies this conference that the {@link #getAudioState()} property has a new value.
158 *
159 * @param state The new call audio state.
160 */
161 public void onAudioStateChanged(AudioState state) {}
162
163 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -0700164 * Sets state to be on hold.
165 */
166 public final void setOnHold() {
167 setState(Connection.STATE_HOLDING);
168 }
169
170 /**
171 * Sets state to be active.
172 */
173 public final void setActive() {
174 setState(Connection.STATE_ACTIVE);
175 }
176
177 /**
178 * Sets state to disconnected.
179 *
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700180 * @param disconnectCause The reason for the disconnection, as described by
181 * {@link android.telecom.DisconnectCause}.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700182 */
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700183 public final void setDisconnected(DisconnectCause disconnectCause) {
184 mDisconnectCause = disconnectCause;;
Santos Cordon823fd3c2014-08-07 18:35:18 -0700185 setState(Connection.STATE_DISCONNECTED);
186 for (Listener l : mListeners) {
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700187 l.onDisconnected(this, mDisconnectCause);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700188 }
189 }
190
191 /**
Nancy Chen56fc25d2014-09-09 12:24:51 -0700192 * Sets the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
193 *
194 * @param capabilities A bitmask of the {@code PhoneCapabilities} of the conference call.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700195 */
196 public final void setCapabilities(int capabilities) {
197 if (capabilities != mCapabilities) {
198 mCapabilities = capabilities;
199
200 for (Listener l : mListeners) {
201 l.onCapabilitiesChanged(this, mCapabilities);
202 }
203 }
204 }
205
206 /**
207 * Adds the specified connection as a child of this conference.
208 *
209 * @param connection The connection to add.
210 * @return True if the connection was successfully added.
211 */
Santos Cordona4868042014-09-04 17:39:22 -0700212 public final boolean addConnection(Connection connection) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700213 if (connection != null && !mChildConnections.contains(connection)) {
214 if (connection.setConference(this)) {
215 mChildConnections.add(connection);
216 for (Listener l : mListeners) {
217 l.onConnectionAdded(this, connection);
218 }
219 return true;
220 }
221 }
222 return false;
223 }
224
225 /**
226 * Removes the specified connection as a child of this conference.
227 *
228 * @param connection The connection to remove.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700229 */
Santos Cordona4868042014-09-04 17:39:22 -0700230 public final void removeConnection(Connection connection) {
Santos Cordon0159ac02014-08-21 14:28:11 -0700231 Log.d(this, "removing %s from %s", connection, mChildConnections);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700232 if (connection != null && mChildConnections.remove(connection)) {
233 connection.resetConference();
234 for (Listener l : mListeners) {
235 l.onConnectionRemoved(this, connection);
236 }
237 }
238 }
239
240 /**
Nancy Chenea38cca2014-09-05 16:38:49 -0700241 * Tears down the conference object and any of its current connections.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700242 */
Santos Cordona4868042014-09-04 17:39:22 -0700243 public final void destroy() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700244 Log.d(this, "destroying conference : %s", this);
245 // Tear down the children.
Santos Cordon0159ac02014-08-21 14:28:11 -0700246 for (Connection connection : mChildConnections) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700247 Log.d(this, "removing connection %s", connection);
248 removeConnection(connection);
249 }
250
251 // If not yet disconnected, set the conference call as disconnected first.
252 if (mState != Connection.STATE_DISCONNECTED) {
253 Log.d(this, "setting to disconnected");
Andrew Lee7f3d41f2014-09-11 17:33:16 -0700254 setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
Santos Cordon823fd3c2014-08-07 18:35:18 -0700255 }
256
257 // ...and notify.
258 for (Listener l : mListeners) {
259 l.onDestroyed(this);
260 }
261 }
262
263 /**
264 * Add a listener to be notified of a state change.
265 *
266 * @param listener The new listener.
267 * @return This conference.
268 * @hide
269 */
270 public final Conference addListener(Listener listener) {
271 mListeners.add(listener);
272 return this;
273 }
274
275 /**
276 * Removes the specified listener.
277 *
278 * @param listener The listener to remove.
279 * @return This conference.
280 * @hide
281 */
282 public final Conference removeListener(Listener listener) {
283 mListeners.remove(listener);
284 return this;
285 }
286
Yorke Leea0d3ca92014-09-15 19:18:13 -0700287 /**
288 * Inform this Conference that the state of its audio output has been changed externally.
289 *
290 * @param state The new audio state.
291 * @hide
292 */
293 final void setAudioState(AudioState state) {
294 Log.d(this, "setAudioState %s", state);
295 mAudioState = state;
296 onAudioStateChanged(state);
297 }
298
Santos Cordon823fd3c2014-08-07 18:35:18 -0700299 private void setState(int newState) {
300 if (newState != Connection.STATE_ACTIVE &&
301 newState != Connection.STATE_HOLDING &&
302 newState != Connection.STATE_DISCONNECTED) {
303 Log.w(this, "Unsupported state transition for Conference call.",
304 Connection.stateToString(newState));
305 return;
306 }
307
308 if (mState != newState) {
309 int oldState = mState;
310 mState = newState;
311 for (Listener l : mListeners) {
312 l.onStateChanged(this, oldState, newState);
313 }
314 }
315 }
316}