blob: ca854460fba2d164f21e6344b3a1abdc6047a8b3 [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
19import android.telephony.DisconnectCause;
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.
29 */
30public abstract class Conference {
31
32 /** @hide */
33 public abstract static class Listener {
34 public void onStateChanged(Conference conference, int oldState, int newState) {}
35 public void onDisconnected(Conference conference, int cause, String message) {}
36 public void onConnectionAdded(Conference conference, Connection connection) {}
37 public void onConnectionRemoved(Conference conference, Connection connection) {}
38 public void onDestroyed(Conference conference) {}
39 public void onCapabilitiesChanged(Conference conference, int capabilities) {}
40 }
41
42 private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
43 private final List<Connection> mChildConnections = new CopyOnWriteArrayList<>();
Ihab Awadb8e85c72014-08-23 20:34:57 -070044 private final List<Connection> mUnmodifiableChildConnections =
Santos Cordon823fd3c2014-08-07 18:35:18 -070045 Collections.unmodifiableList(mChildConnections);
46
47 private PhoneAccountHandle mPhoneAccount;
48 private int mState = Connection.STATE_NEW;
49 private int mDisconnectCause = DisconnectCause.NOT_VALID;
50 private int mCapabilities;
51 private String mDisconnectMessage;
52
Nancy Chen56fc25d2014-09-09 12:24:51 -070053 /**
54 * Constructs a new Conference with a mandatory {@link PhoneAccountHandle}
55 *
56 * @param phoneAccount The {@code PhoneAccountHandle} associated with the conference.
57 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070058 public Conference(PhoneAccountHandle phoneAccount) {
59 mPhoneAccount = phoneAccount;
60 }
61
Nancy Chen56fc25d2014-09-09 12:24:51 -070062 /**
63 * Returns the {@link PhoneAccountHandle} the conference call is being placed through.
64 *
65 * @return A {@code PhoneAccountHandle} object representing the PhoneAccount of the conference.
66 */
Nancy Chenea38cca2014-09-05 16:38:49 -070067 public final PhoneAccountHandle getPhoneAccountHandle() {
Santos Cordon823fd3c2014-08-07 18:35:18 -070068 return mPhoneAccount;
69 }
70
Nancy Chen56fc25d2014-09-09 12:24:51 -070071 /**
72 * Returns the list of connections currently associated with the conference call.
73 *
74 * @return A list of {@code Connection} objects which represent the children of the conference.
75 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070076 public final List<Connection> getConnections() {
Ihab Awadb8e85c72014-08-23 20:34:57 -070077 return mUnmodifiableChildConnections;
Santos Cordon823fd3c2014-08-07 18:35:18 -070078 }
79
Nancy Chen56fc25d2014-09-09 12:24:51 -070080 /**
81 * Gets the state of the conference call. See {@link Connection} for valid values.
82 *
83 * @return A constant representing the state the conference call is currently in.
84 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070085 public final int getState() {
86 return mState;
87 }
88
Nancy Chen56fc25d2014-09-09 12:24:51 -070089 /**
90 * Returns the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
91 *
92 * @return A bitmask of the {@code PhoneCapabilities} of the conference call.
93 */
Santos Cordon823fd3c2014-08-07 18:35:18 -070094 public final int getCapabilities() {
95 return mCapabilities;
96 }
97
98 /**
99 * Invoked when the Conference and all it's {@link Connection}s should be disconnected.
100 */
101 public void onDisconnect() {}
102
103 /**
104 * Invoked when the specified {@link Connection} should be separated from the conference call.
105 *
106 * @param connection The connection to separate.
107 */
108 public void onSeparate(Connection connection) {}
109
110 /**
111 * Invoked when the conference should be put on hold.
112 */
113 public void onHold() {}
114
115 /**
116 * Invoked when the conference should be moved from hold to active.
117 */
118 public void onUnhold() {}
119
120 /**
Santos Cordona4868042014-09-04 17:39:22 -0700121 * Invoked when the child calls should be merged. Only invoked if the conference contains the
122 * capability {@link PhoneCapabilities#MERGE_CONFERENCE}.
123 */
124 public void onMerge() {}
125
126 /**
127 * Invoked when the child calls should be swapped. Only invoked if the conference contains the
128 * capability {@link PhoneCapabilities#SWAP_CONFERENCE}.
129 */
130 public void onSwap() {}
131
132 /**
Santos Cordon823fd3c2014-08-07 18:35:18 -0700133 * Sets state to be on hold.
134 */
135 public final void setOnHold() {
136 setState(Connection.STATE_HOLDING);
137 }
138
139 /**
140 * Sets state to be active.
141 */
142 public final void setActive() {
143 setState(Connection.STATE_ACTIVE);
144 }
145
146 /**
147 * Sets state to disconnected.
148 *
149 * @param cause The reason for the disconnection, any of
150 * {@link android.telephony.DisconnectCause}.
151 * @param message Optional call-service-provided message about the disconnect.
152 */
153 public final void setDisconnected(int cause, String message) {
154 mDisconnectCause = cause;
155 mDisconnectMessage = message;
156 setState(Connection.STATE_DISCONNECTED);
157 for (Listener l : mListeners) {
158 l.onDisconnected(this, mDisconnectCause, mDisconnectMessage);
159 }
160 }
161
162 /**
Nancy Chen56fc25d2014-09-09 12:24:51 -0700163 * Sets the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
164 *
165 * @param capabilities A bitmask of the {@code PhoneCapabilities} of the conference call.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700166 */
167 public final void setCapabilities(int capabilities) {
168 if (capabilities != mCapabilities) {
169 mCapabilities = capabilities;
170
171 for (Listener l : mListeners) {
172 l.onCapabilitiesChanged(this, mCapabilities);
173 }
174 }
175 }
176
177 /**
178 * Adds the specified connection as a child of this conference.
179 *
180 * @param connection The connection to add.
181 * @return True if the connection was successfully added.
182 */
Santos Cordona4868042014-09-04 17:39:22 -0700183 public final boolean addConnection(Connection connection) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700184 if (connection != null && !mChildConnections.contains(connection)) {
185 if (connection.setConference(this)) {
186 mChildConnections.add(connection);
187 for (Listener l : mListeners) {
188 l.onConnectionAdded(this, connection);
189 }
190 return true;
191 }
192 }
193 return false;
194 }
195
196 /**
197 * Removes the specified connection as a child of this conference.
198 *
199 * @param connection The connection to remove.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700200 */
Santos Cordona4868042014-09-04 17:39:22 -0700201 public final void removeConnection(Connection connection) {
Santos Cordon0159ac02014-08-21 14:28:11 -0700202 Log.d(this, "removing %s from %s", connection, mChildConnections);
Santos Cordon823fd3c2014-08-07 18:35:18 -0700203 if (connection != null && mChildConnections.remove(connection)) {
204 connection.resetConference();
205 for (Listener l : mListeners) {
206 l.onConnectionRemoved(this, connection);
207 }
208 }
209 }
210
211 /**
Nancy Chenea38cca2014-09-05 16:38:49 -0700212 * Tears down the conference object and any of its current connections.
Santos Cordon823fd3c2014-08-07 18:35:18 -0700213 */
Santos Cordona4868042014-09-04 17:39:22 -0700214 public final void destroy() {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700215 Log.d(this, "destroying conference : %s", this);
216 // Tear down the children.
Santos Cordon0159ac02014-08-21 14:28:11 -0700217 for (Connection connection : mChildConnections) {
Santos Cordon823fd3c2014-08-07 18:35:18 -0700218 Log.d(this, "removing connection %s", connection);
219 removeConnection(connection);
220 }
221
222 // If not yet disconnected, set the conference call as disconnected first.
223 if (mState != Connection.STATE_DISCONNECTED) {
224 Log.d(this, "setting to disconnected");
225 setDisconnected(DisconnectCause.LOCAL, null);
226 }
227
228 // ...and notify.
229 for (Listener l : mListeners) {
230 l.onDestroyed(this);
231 }
232 }
233
234 /**
235 * Add a listener to be notified of a state change.
236 *
237 * @param listener The new listener.
238 * @return This conference.
239 * @hide
240 */
241 public final Conference addListener(Listener listener) {
242 mListeners.add(listener);
243 return this;
244 }
245
246 /**
247 * Removes the specified listener.
248 *
249 * @param listener The listener to remove.
250 * @return This conference.
251 * @hide
252 */
253 public final Conference removeListener(Listener listener) {
254 mListeners.remove(listener);
255 return this;
256 }
257
258 private void setState(int newState) {
259 if (newState != Connection.STATE_ACTIVE &&
260 newState != Connection.STATE_HOLDING &&
261 newState != Connection.STATE_DISCONNECTED) {
262 Log.w(this, "Unsupported state transition for Conference call.",
263 Connection.stateToString(newState));
264 return;
265 }
266
267 if (mState != newState) {
268 int oldState = mState;
269 mState = newState;
270 for (Listener l : mListeners) {
271 l.onStateChanged(this, oldState, newState);
272 }
273 }
274 }
275}