Support conference calling. (2/4)
Bug: 15006702
Change-Id: I2764ea242f783ba478c9eae86618dd33e9fc792a
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index 66f9366..607aeb1 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -40,6 +40,9 @@
import com.google.android.collect.Sets;
import com.google.common.base.Preconditions;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -60,6 +63,11 @@
void onFailedIncomingCall(Call call);
void onRequestingRingback(Call call, boolean requestingRingback);
void onPostDialWait(Call call, String remaining);
+ void onIsConferenceCapableChanged(Call call, boolean isConferenceCapable);
+ void onExpiredConferenceCall(Call call);
+ void onConfirmedConferenceCall(Call call);
+ void onParentChanged(Call call);
+ void onChildrenChanged(Call call);
}
private static final OnQueryCompleteListener sCallerInfoQueryListener =
@@ -180,13 +188,21 @@
/** Incoming call-info to use when direct-to-voicemail query finishes. */
private CallInfo mPendingDirectToVoicemailCallInfo;
+ private boolean mIsConferenceCapable = false;
+
+ private boolean mIsConference = false;
+
+ private Call mParentCall = null;
+
+ private List<Call> mChildCalls = new LinkedList<>();
+
/**
* Creates an empty call object.
*
* @param isIncoming True if this is an incoming call.
*/
- Call(boolean isIncoming) {
- this(null, null, isIncoming);
+ Call(boolean isIncoming, boolean isConference) {
+ this(null, null, isIncoming, isConference);
}
/**
@@ -196,11 +212,12 @@
* @param gatewayInfo Gateway information to use for the call.
* @param isIncoming True if this is an incoming call.
*/
- Call(Uri handle, GatewayInfo gatewayInfo, boolean isIncoming) {
- mState = CallState.NEW;
+ Call(Uri handle, GatewayInfo gatewayInfo, boolean isIncoming, boolean isConference) {
+ mState = isConference ? CallState.ACTIVE : CallState.NEW;
setHandle(handle);
mGatewayInfo = gatewayInfo;
mIsIncoming = isIncoming;
+ mIsConference = isConference;
}
void addListener(Listener listener) {
@@ -221,7 +238,15 @@
}
CallState getState() {
- return mState;
+ if (mIsConference) {
+ if (!mChildCalls.isEmpty()) {
+ // If we have child calls, just return the child call.
+ return mChildCalls.get(0).getState();
+ }
+ return CallState.ACTIVE;
+ } else {
+ return mState;
+ }
}
/**
@@ -343,6 +368,27 @@
mConnectTimeMillis = connectTimeMillis;
}
+ boolean isConferenceCapable() {
+ return mIsConferenceCapable;
+ }
+
+ void setIsConferenceCapable(boolean isConferenceCapable) {
+ if (mIsConferenceCapable != isConferenceCapable) {
+ mIsConferenceCapable = isConferenceCapable;
+ for (Listener l : mListeners) {
+ l.onIsConferenceCapableChanged(this, mIsConferenceCapable);
+ }
+ }
+ }
+
+ Call getParentCall() {
+ return mParentCall;
+ }
+
+ List<Call> getChildCalls() {
+ return mChildCalls;
+ }
+
CallServiceWrapper getCallService() {
return mCallService;
}
@@ -450,7 +496,7 @@
public void run() {
processDirectToVoicemail();
}
- }, Timeouts.getDirectToVoicemail());
+ }, Timeouts.getDirectToVoicemailMillis());
}
void processDirectToVoicemail() {
@@ -740,6 +786,73 @@
getCallService().onPostDialContinue(this, proceed);
}
+ void conferenceInto(Call conferenceCall) {
+ if (mCallService == null) {
+ Log.w(this, "conference requested on a call without a call service.");
+ } else {
+ mCallService.conference(conferenceCall, this);
+ }
+ }
+
+ void expireConference() {
+ // The conference call expired before we got a confirmation of the conference from the
+ // call service...so start shutting down.
+ clearCallService();
+ for (Listener l : mListeners) {
+ l.onExpiredConferenceCall(this);
+ }
+ }
+
+ void confirmConference() {
+ Log.v(this, "confirming Conf call %s", mListeners);
+ for (Listener l : mListeners) {
+ l.onConfirmedConferenceCall(this);
+ }
+ }
+
+ void splitFromConference() {
+ // TODO(santoscordon): todo
+ }
+
+ void setParentCall(Call parentCall) {
+ if (parentCall == this) {
+ Log.e(this, new Exception(), "setting the parent to self");
+ return;
+ }
+ Preconditions.checkState(parentCall == null || mParentCall == null);
+
+ Call oldParent = mParentCall;
+ if (mParentCall != null) {
+ mParentCall.removeChildCall(this);
+ }
+ mParentCall = parentCall;
+ if (mParentCall != null) {
+ mParentCall.addChildCall(this);
+ }
+
+ for (Listener l : mListeners) {
+ l.onParentChanged(this);
+ }
+ }
+
+ private void addChildCall(Call call) {
+ if (!mChildCalls.contains(call)) {
+ mChildCalls.add(call);
+
+ for (Listener l : mListeners) {
+ l.onChildrenChanged(this);
+ }
+ }
+ }
+
+ private void removeChildCall(Call call) {
+ if (mChildCalls.remove(call)) {
+ for (Listener l : mListeners) {
+ l.onChildrenChanged(this);
+ }
+ }
+ }
+
/**
* @return True if the call is ringing, else logs the action name.
*/
diff --git a/src/com/android/telecomm/CallIdMapper.java b/src/com/android/telecomm/CallIdMapper.java
index 7f92067..e6b5c1f 100644
--- a/src/com/android/telecomm/CallIdMapper.java
+++ b/src/com/android/telecomm/CallIdMapper.java
@@ -38,12 +38,15 @@
mCalls.put(callId, newCall);
}
+ void addCall(Call call, String id) {
+ Preconditions.checkNotNull(call);
+ ThreadUtil.checkOnMainThread();
+ mCalls.put(id, call);
+ }
+
void addCall(Call call) {
ThreadUtil.checkOnMainThread();
- Preconditions.checkNotNull(call);
- sIdCount++;
- String callId = mCallIdPrefix + sIdCount;
- mCalls.put(callId, call);
+ addCall(call, getNewId());
}
void removeCall(Call call) {
@@ -91,4 +94,9 @@
// Note, no need for thread check, this method is thread safe.
return callId != null && callId.startsWith(mCallIdPrefix);
}
+
+ String getNewId() {
+ sIdCount++;
+ return mCallIdPrefix + sIdCount;
+ }
}
diff --git a/src/com/android/telecomm/CallServiceWrapper.java b/src/com/android/telecomm/CallServiceWrapper.java
index 6165804..4462cff 100644
--- a/src/com/android/telecomm/CallServiceWrapper.java
+++ b/src/com/android/telecomm/CallServiceWrapper.java
@@ -35,11 +35,11 @@
import com.android.internal.telecomm.ICallServiceProvider;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Sets;
import org.apache.http.conn.ClientConnectionRequest;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -50,6 +50,7 @@
* and instead should use this class to invoke methods of {@link ICallService}.
*/
final class CallServiceWrapper extends ServiceBinder<ICallService> {
+ private static final String TAG = CallServiceWrapper.class.getSimpleName();
private final class Adapter extends ICallServiceAdapter.Stub {
private static final int MSG_NOTIFY_INCOMING_CALL = 1;
@@ -62,7 +63,10 @@
private static final int MSG_SET_ON_HOLD = 8;
private static final int MSG_SET_REQUESTING_RINGBACK = 9;
private static final int MSG_ON_POST_DIAL_WAIT = 10;
- private static final int MSG_HANDOFF_CALL = 11;
+ private static final int MSG_CAN_CONFERENCE = 11;
+ private static final int MSG_SET_IS_CONFERENCED = 12;
+ private static final int MSG_ADD_CONFERENCE_CALL = 13;
+ private static final int MSG_HANDOFF_CALL = 14;
private final Handler mHandler = new Handler() {
@Override
@@ -79,8 +83,7 @@
mIncomingCallsManager.handleSuccessfulIncomingCall(call, callInfo);
} else {
Log.w(this, "notifyIncomingCall, unknown incoming call: %s, id: %s",
- call,
- clientCallInfo.getId());
+ call, clientCallInfo.getId());
}
break;
case MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL: {
@@ -176,7 +179,7 @@
}
break;
}
- case MSG_ON_POST_DIAL_WAIT:
+ case MSG_ON_POST_DIAL_WAIT: {
SomeArgs args = (SomeArgs) msg.obj;
try {
call = mCallIdMapper.getCall(args.arg1);
@@ -189,6 +192,8 @@
} finally {
args.recycle();
}
+ break;
+ }
case MSG_HANDOFF_CALL:
call = mCallIdMapper.getCall(msg.obj);
if (call != null) {
@@ -197,6 +202,63 @@
Log.w(this, "handoffCall, unknown call id: %s", msg.obj);
}
break;
+ case MSG_CAN_CONFERENCE: {
+ call = mCallIdMapper.getCall(msg.obj);
+ if (call != null) {
+ call.setIsConferenceCapable(msg.arg1 == 1);
+ } else {
+ Log.w(CallServiceWrapper.this, "canConference, unknown call id: %s",
+ msg.obj);
+ }
+ break;
+ }
+ case MSG_SET_IS_CONFERENCED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ Call childCall = mCallIdMapper.getCall(args.arg1);
+ if (childCall != null) {
+ String conferenceCallId = (String) args.arg2;
+ Log.d(this, "setIsConferenced %s, %s", childCall, conferenceCallId);
+
+ if (conferenceCallId == null) {
+ childCall.setParentCall(null);
+ } else {
+ Call conferenceCall = mCallIdMapper.getCall(conferenceCallId);
+ if (conferenceCall != null &&
+ !mPendingConferenceCalls.contains(conferenceCall)) {
+ childCall.setParentCall(conferenceCall);
+ } else {
+ Log.w(this, "setIsConferenced, unknown conference id %s",
+ conferenceCallId);
+ }
+ }
+ } else {
+ Log.w(this, "setIsConferenced, unknown call id: %s", args.arg1);
+ }
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_ADD_CONFERENCE_CALL: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ String callId = (String) args.arg1;
+ Log.d(this, "addConferenceCall attempt %s, %s",
+ callId, mPendingConferenceCalls);
+
+ Call conferenceCall = mCallIdMapper.getCall(callId);
+ if (mPendingConferenceCalls.remove(conferenceCall)) {
+ Log.v(this, "confirming conf call %s", conferenceCall);
+ conferenceCall.confirmConference();
+ } else {
+ Log.w(this, "addConference, unknown call id: %s", callId);
+ }
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
}
}
};
@@ -294,12 +356,29 @@
/** ${inheritDoc} */
@Override
- public void setCanConferenceWith(String callId, List<String> conferenceCapableCallIds) {
+ public void setCanConference(String callId, boolean canConference) {
+ Log.d(this, "setCanConference(%s, %b)", callId, canConference);
+ mHandler.obtainMessage(MSG_CAN_CONFERENCE, canConference ? 1 : 0, 0, callId)
+ .sendToTarget();
}
/** ${inheritDoc} */
@Override
- public void setIsConferenced(String conferenceCallId, String callId, boolean isConferenced) {
+ public void setIsConferenced(String callId, String conferenceCallId) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = conferenceCallId;
+ mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
+ }
+
+ /** ${InheritDoc} */
+ @Override
+ public void addConferenceCall(String callId, CallInfo callInfo) {
+ mCallIdMapper.checkValidCallId(callId);
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = callInfo;
+ mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, args).sendToTarget();
}
@Override
@@ -321,11 +400,13 @@
private final Adapter mAdapter = new Adapter();
private final CallsManager mCallsManager = CallsManager.getInstance();
- private final Set<Call> mPendingIncomingCalls = Sets.newHashSet();
+ private final Set<Call> mPendingIncomingCalls = new HashSet<>();
+ private final Set<Call> mPendingConferenceCalls = new HashSet<>();
private final CallServiceDescriptor mDescriptor;
private final CallIdMapper mCallIdMapper = new CallIdMapper("CallService");
private final IncomingCallsManager mIncomingCallsManager;
private final Map<String, AsyncResultCallback<Boolean>> mPendingOutgoingCalls = new HashMap<>();
+ private final Handler mHandler = new Handler();
private Binder mBinder = new Binder();
private ICallService mServiceInterface;
@@ -521,7 +602,9 @@
}
void addCall(Call call) {
- mCallIdMapper.addCall(call);
+ if (mCallIdMapper.getCallId(call) == null) {
+ mCallIdMapper.addCall(call);
+ }
}
/**
@@ -553,6 +636,37 @@
}
}
+ void conference(final Call conferenceCall, Call call) {
+ if (isServiceValid("conference")) {
+ try {
+ conferenceCall.setCallService(this);
+ mPendingConferenceCalls.add(conferenceCall);
+ mHandler.postDelayed(new Runnable() {
+ @Override public void run() {
+ if (mPendingConferenceCalls.remove(conferenceCall)) {
+ conferenceCall.expireConference();
+ Log.i(this, "Conference call expired: %s", conferenceCall);
+ }
+ }
+ }, Timeouts.getConferenceCallExpireMillis());
+
+ mServiceInterface.conference(
+ mCallIdMapper.getCallId(conferenceCall),
+ mCallIdMapper.getCallId(call));
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ void splitFromConference(Call call) {
+ if (isServiceValid("splitFromConference")) {
+ try {
+ mServiceInterface.splitFromConference(mCallIdMapper.getCallId(call));
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
/** {@inheritDoc} */
@Override
protected void setServiceInterface(IBinder binder) {
@@ -589,12 +703,12 @@
mIncomingCallsManager.handleFailedIncomingCall(call);
}
- if (!mPendingIncomingCalls.isEmpty()) {
- Log.wtf(this, "Pending calls did not get cleared.");
- mPendingIncomingCalls.clear();
- }
- }
+ if (!mPendingIncomingCalls.isEmpty()) {
+ Log.wtf(this, "Pending calls did not get cleared.");
+ mPendingIncomingCalls.clear();
+ }
+ }
- mCallIdMapper.clear();
- }
+ mCallIdMapper.clear();
+ }
}
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index 9a9e235..6057350 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -61,6 +61,8 @@
void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall);
void onAudioStateChanged(CallAudioState oldAudioState, CallAudioState newAudioState);
void onRequestingRingback(Call call, boolean ringback);
+ void onIsConferenceCapableChanged(Call call, boolean isConferenceCapable);
+ void onIsConferencedChanged(Call call);
}
private static final CallsManager INSTANCE = new CallsManager();
@@ -165,6 +167,13 @@
}
@Override
+ public void onIsConferenceCapableChanged(Call call, boolean isConferenceCapable) {
+ for (CallsManagerListener listener : mListeners) {
+ listener.onIsConferenceCapableChanged(call, isConferenceCapable);
+ }
+ }
+
+ @Override
public void onRequestingRingback(Call call, boolean ringback) {
for (CallsManagerListener listener : mListeners) {
listener.onRequestingRingback(call, ringback);
@@ -176,6 +185,34 @@
mInCallController.onPostDialWait(call, remaining);
}
+ @Override
+ public void onExpiredConferenceCall(Call call) {
+ call.removeListener(this);
+ }
+
+ @Override
+ public void onConfirmedConferenceCall(Call call) {
+ addCall(call);
+ Log.v(this, "confirming Conf call %s", call);
+ for (CallsManagerListener listener : mListeners) {
+ listener.onIsConferencedChanged(call);
+ }
+ }
+
+ @Override
+ public void onParentChanged(Call call) {
+ for (CallsManagerListener listener : mListeners) {
+ listener.onIsConferencedChanged(call);
+ }
+ }
+
+ @Override
+ public void onChildrenChanged(Call call) {
+ for (CallsManagerListener listener : mListeners) {
+ listener.onIsConferencedChanged(call);
+ }
+ }
+
ImmutableCollection<Call> getCalls() {
return ImmutableList.copyOf(mCalls);
}
@@ -218,7 +255,7 @@
// Create a call with no handle. Eventually, switchboard will update the call with
// additional information from the call service, but for now we just need one to pass
// around.
- Call call = new Call(true /* isIncoming */);
+ Call call = new Call(true /* isIncoming */, false /* isConference */);
// TODO(santoscordon): Move this to be a part of addCall()
call.addListener(this);
@@ -243,7 +280,8 @@
Log.pii(uriHandle), Log.pii(handle));
}
- Call call = new Call(uriHandle, gatewayInfo, false /* isIncoming */);
+ Call call = new Call(
+ uriHandle, gatewayInfo, false /* isIncoming */, false /* isConference */);
// TODO(santoscordon): Move this to be a part of addCall()
call.addListener(this);
@@ -253,6 +291,17 @@
}
/**
+ * Attempts to start a conference call for the specified call.
+ *
+ * @param call The call to conference with.
+ */
+ void conference(Call call) {
+ Call conferenceCall = new Call(false, true);
+ conferenceCall.addListener(this);
+ call.conferenceInto(conferenceCall);
+ }
+
+ /**
* Instructs Telecomm to answer the specified call. Intended to be invoked by the in-call
* app through {@link InCallAdapter} after Telecomm notifies it of an incoming call followed by
* the user opting to answer said call.
@@ -410,8 +459,8 @@
// original call will live on but its state will be updated to the new call's state. In
// particular the original call's call service will be updated to the new call's call
// service.
- Call tempCall =
- new Call(originalCall.getHandoffHandle(), originalCall.getGatewayInfo(), false);
+ Call tempCall = new Call(
+ originalCall.getHandoffHandle(), originalCall.getGatewayInfo(), false, false);
tempCall.setOriginalCall(originalCall);
tempCall.setExtras(originalCall.getExtras());
tempCall.setCallServiceSelector(originalCall.getCallServiceSelector());
diff --git a/src/com/android/telecomm/CallsManagerListenerBase.java b/src/com/android/telecomm/CallsManagerListenerBase.java
index d3ea758..60fdbf6 100644
--- a/src/com/android/telecomm/CallsManagerListenerBase.java
+++ b/src/com/android/telecomm/CallsManagerListenerBase.java
@@ -74,4 +74,12 @@
@Override
public void onRequestingRingback(Call call, boolean ringback) {
}
+
+ @Override
+ public void onIsConferenceCapableChanged(Call call, boolean isConferenceCapable) {
+ }
+
+ @Override
+ public void onIsConferencedChanged(Call call) {
+ }
}
diff --git a/src/com/android/telecomm/InCallAdapter.java b/src/com/android/telecomm/InCallAdapter.java
index 0dfcae8..7ae12ab 100644
--- a/src/com/android/telecomm/InCallAdapter.java
+++ b/src/com/android/telecomm/InCallAdapter.java
@@ -39,6 +39,8 @@
private static final int MSG_HANDOFF_CALL = 8;
private static final int MSG_MUTE = 9;
private static final int MSG_SET_AUDIO_ROUTE = 10;
+ private static final int MSG_CONFERENCE = 11;
+ private static final int MSG_SPLIT_FROM_CONFERENCE = 12;
private final class InCallAdapterHandler extends Handler {
@Override
@@ -86,6 +88,12 @@
case MSG_SET_AUDIO_ROUTE:
mCallsManager.setAudioRoute(msg.arg1);
break;
+ case MSG_CONFERENCE:
+ mCallsManager.conference(call);
+ break;
+ case MSG_SPLIT_FROM_CONFERENCE:
+ call.splitFromConference();
+ break;
}
}
}
@@ -184,11 +192,13 @@
/** ${inheritDoc} */
@Override
- public void conferenceWith(String arg0, String arg1) {
+ public void conference(String callId) {
+ mHandler.obtainMessage(MSG_CONFERENCE, callId).sendToTarget();
}
/** ${inheritDoc} */
@Override
- public void splitFromConference(String arg0) {
+ public void splitFromConference(String callId) {
+ mHandler.obtainMessage(MSG_SPLIT_FROM_CONFERENCE, callId).sendToTarget();
}
}
diff --git a/src/com/android/telecomm/InCallController.java b/src/com/android/telecomm/InCallController.java
index 637e03e..434c709 100644
--- a/src/com/android/telecomm/InCallController.java
+++ b/src/com/android/telecomm/InCallController.java
@@ -34,6 +34,10 @@
import com.android.internal.telecomm.IInCallService;
import com.google.common.collect.ImmutableCollection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
/**
* Binds to {@link IInCallService} and provides the service to {@link CallsManager} through which it
* can send updates to the in-call app. This class is created and owned by CallsManager and retains
@@ -153,6 +157,17 @@
}
}
+ @Override
+ public void onIsConferenceCapableChanged(Call call, boolean isConferenceCapable) {
+ updateCall(call);
+ }
+
+ @Override
+ public void onIsConferencedChanged(Call call) {
+ Log.v(this, "onIsConferencedChanged %s", call);
+ updateCall(call);
+ }
+
void bringToForeground(boolean showDialpad) {
if (mInCallService != null) {
try {
@@ -243,7 +258,9 @@
private void updateCall(Call call) {
if (mInCallService != null) {
try {
- mInCallService.updateCall(toInCallCall(call));
+ InCallCall inCallCall = toInCallCall(call);
+ Log.v(this, "updateCall %s ==> %s", call, inCallCall);
+ mInCallService.updateCall(inCallCall);
} catch (RemoteException ignored) {
}
}
@@ -262,6 +279,9 @@
if (CallsManager.getInstance().isAddCallCapable(call)) {
capabilities |= CallCapabilities.ADD_CALL;
}
+ if (call.isConferenceCapable()) {
+ capabilities |= CallCapabilities.MERGE_CALLS;
+ }
CallState state = call.getState();
if (state == CallState.ABORTED) {
state = CallState.DISCONNECTED;
@@ -270,9 +290,27 @@
if (state == CallState.DISCONNECTED && call.getHandoffCallServiceDescriptor() != null) {
state = CallState.ACTIVE;
}
+
+ String parentCallId = null;
+ Call parentCall = call.getParentCall();
+ if (parentCall != null) {
+ parentCallId = mCallIdMapper.getCallId(parentCall);
+ }
+
+ long connectTimeMillis = call.getConnectTimeMillis();
+ List<Call> childCalls = call.getChildCalls();
+ List<String> childCallIds = new ArrayList<>();
+ if (!childCalls.isEmpty()) {
+ connectTimeMillis = Long.MAX_VALUE;
+ for (Call child : childCalls) {
+ connectTimeMillis = Math.min(child.getConnectTimeMillis(), connectTimeMillis);
+ childCallIds.add(mCallIdMapper.getCallId(child));
+ }
+ }
+
return new InCallCall(callId, state, call.getDisconnectCause(), call.getDisconnectMessage(),
- capabilities, call.getConnectTimeMillis(), call.getHandle(), call.getGatewayInfo(),
- descriptor, call.getHandoffCallServiceDescriptor());
+ capabilities, connectTimeMillis, call.getHandle(), call.getGatewayInfo(),
+ descriptor, call.getHandoffCallServiceDescriptor(), parentCallId, childCallIds);
}
}
diff --git a/src/com/android/telecomm/Timeouts.java b/src/com/android/telecomm/Timeouts.java
index d13091f..3e5899c 100644
--- a/src/com/android/telecomm/Timeouts.java
+++ b/src/com/android/telecomm/Timeouts.java
@@ -65,7 +65,14 @@
* to complete. If the query goes beyond this timeout, the incoming call screen is shown to the
* user.
*/
- public static long getDirectToVoicemail() {
+ public static long getDirectToVoicemailMillis() {
return get("direct_to_voicemail_ms", 500L);
}
+
+ /**
+ * Returns the amount of time that a connection service has to respond to a "conference" action.
+ */
+ public static long getConferenceCallExpireMillis() {
+ return get("conference_call_expire_ms", 15 * 1000L);
+ }
}
diff --git a/tests/src/com/android/telecomm/testapps/TestCallService.java b/tests/src/com/android/telecomm/testapps/TestCallService.java
index d34a2d2..67626a2 100644
--- a/tests/src/com/android/telecomm/testapps/TestCallService.java
+++ b/tests/src/com/android/telecomm/testapps/TestCallService.java
@@ -185,12 +185,12 @@
/** ${inheritDoc} */
@Override
- public void addToConference(String conferenceCallId, List<String> callIds) {
+ public void conference(String conferenceCallId, String callId) {
}
/** ${inheritDoc} */
@Override
- public void splitFromConference(String conferenceCallId, String callId) {
+ public void splitFromConference(String callId) {
}
private void activateCall(String callId) {