Make add-call a global property of telecom. (2/4)
ADD_CALL didn't make sense as a property of Connection or Call.
This changes it to be a global property instead.
Bug: 18285352
Change-Id: I5189e114e74dba2d81d74c6d24cf5b17f1e0922a
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index b677b85..57b9e8e 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -74,6 +74,7 @@
void onIsConferencedChanged(Call call);
void onIsVoipAudioModeChanged(Call call);
void onVideoStateChanged(Call call);
+ void onCanAddCallChanged(boolean canAddCall);
}
/**
@@ -87,13 +88,14 @@
private static final int MAXIMUM_HOLD_CALLS = 1;
private static final int MAXIMUM_RINGING_CALLS = 1;
private static final int MAXIMUM_OUTGOING_CALLS = 1;
-
- private static final int[] LIVE_CALL_STATES =
- {CallState.CONNECTING, CallState.PRE_DIAL_WAIT, CallState.DIALING, CallState.ACTIVE};
+ private static final int MAXIMUM_TOP_LEVEL_CALLS = 2;
private static final int[] OUTGOING_CALL_STATES =
{CallState.CONNECTING, CallState.PRE_DIAL_WAIT, CallState.DIALING};
+ private static final int[] LIVE_CALL_STATES =
+ {CallState.CONNECTING, CallState.PRE_DIAL_WAIT, CallState.DIALING, CallState.ACTIVE};
+
/**
* The main call repository. Keeps an instance of all live calls. New incoming and outgoing
* calls are added to the map and removed when the calls move to the disconnected state.
@@ -128,6 +130,8 @@
/* Handler tied to thread in which CallManager was initialized. */
private final Handler mHandler = new Handler();
+ private boolean mCanAddCall = true;
+
/**
* The call the user is currently interacting with. This is the call that should have audio
* focus and be visible in the in-call UI.
@@ -263,7 +267,7 @@
@Override
public void onParentChanged(Call call) {
// parent-child relationship affects which call should be foreground, so do an update.
- updateForegroundCall();
+ updateCallsManagerState();
for (CallsManagerListener listener : mListeners) {
listener.onIsConferencedChanged(call);
}
@@ -272,7 +276,7 @@
@Override
public void onChildrenChanged(Call call) {
// parent-child relationship affects which call should be foreground, so do an update.
- updateForegroundCall();
+ updateCallsManagerState();
for (CallsManagerListener listener : mListeners) {
listener.onIsConferencedChanged(call);
}
@@ -884,22 +888,24 @@
}
/**
- * Checks to see if the specified call is the only top level call. If it is not, we should
- * remove the ADD_CALL capability. We allow you to add a second call but not a third or beyond.
- *
- * @param call The call to check to see if it is the only top level call.
- * @return Whether the call is the only top level call.
+ * Returns true if telecom supports adding another top-level call.
*/
- protected boolean isOnlyTopLevelCall(Call call) {
- if (call.getParentCall() != null) {
- // Never true for child calls.
- return false;
- }
+ boolean canAddCall() {
+ int count = 0;
+ for (Call call : mCalls) {
+ if (call.isEmergencyCall()) {
+ // We never support add call if one of the calls is an emergency call.
+ return false;
+ } else if (call.getParentCall() == null) {
+ count++;
+ }
- // Loop through all the other calls and there exists a top level (has no parent) call
- // that is not the specified call, return false.
- for (Call otherCall : mCalls) {
- if (call != otherCall && otherCall.getParentCall() == null) {
+ // We do not check states for canAddCall. We treat disconnected calls the same
+ // and wait until they are removed instead. If we didn't count disconnected calls,
+ // we could put InCallServices into a state where they are showing two calls but
+ // also support add-call. Technically it's right, but overall looks better (UI-wise)
+ // and acts better if we wait until the call is removed.
+ if (count >= MAXIMUM_TOP_LEVEL_CALLS) {
return false;
}
}
@@ -1033,7 +1039,7 @@
for (CallsManagerListener listener : mListeners) {
listener.onCallAdded(call);
}
- updateForegroundCall();
+ updateCallsManagerState();
}
private void removeCall(Call call) {
@@ -1054,15 +1060,7 @@
for (CallsManagerListener listener : mListeners) {
listener.onCallRemoved(call);
}
- updateForegroundCall();
- }
-
- // Now that a call has been removed, other calls may gain new call capabilities (for
- // example, if only one call is left, it is now add-call capable again). Trigger the
- // recalculation of the call's current capabilities by forcing an update. (See
- // InCallController.toParcelableCall()).
- for (Call otherCall : mCalls) {
- otherCall.setCallCapabilities(otherCall.getCallCapabilities(), true /* forceUpdate */);
+ updateCallsManagerState();
}
}
@@ -1094,7 +1092,7 @@
for (CallsManagerListener listener : mListeners) {
listener.onCallStateChanged(call, oldState, newState);
}
- updateForegroundCall();
+ updateCallsManagerState();
}
}
}
@@ -1138,6 +1136,21 @@
}
}
+ private void updateCanAddCall() {
+ boolean newCanAddCall = canAddCall();
+ if (newCanAddCall != mCanAddCall) {
+ mCanAddCall = newCanAddCall;
+ for (CallsManagerListener listener : mListeners) {
+ listener.onCanAddCallChanged(mCanAddCall);
+ }
+ }
+ }
+
+ private void updateCallsManagerState() {
+ updateForegroundCall();
+ updateCanAddCall();
+ }
+
private boolean isPotentialMMICode(Uri handle) {
return (handle != null && handle.getSchemeSpecificPart() != null
&& handle.getSchemeSpecificPart().contains("#"));
@@ -1174,7 +1187,7 @@
int count = 0;
for (int state : states) {
for (Call call : mCalls) {
- if (call.getState() == state) {
+ if (call.getParentCall() == null && call.getState() == state) {
count++;
}
}
diff --git a/src/com/android/server/telecom/CallsManagerListenerBase.java b/src/com/android/server/telecom/CallsManagerListenerBase.java
index 93b2a24..ffc5947 100644
--- a/src/com/android/server/telecom/CallsManagerListenerBase.java
+++ b/src/com/android/server/telecom/CallsManagerListenerBase.java
@@ -72,4 +72,8 @@
@Override
public void onVideoStateChanged(Call call) {
}
+
+ @Override
+ public void onCanAddCallChanged(boolean canAddCall) {
+ }
}
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 0a15ee6..46fdcdb 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -210,6 +210,19 @@
}
}
+ @Override
+ public void onCanAddCallChanged(boolean canAddCall) {
+ if (!mInCallServices.isEmpty()) {
+ Log.i(this, "onCanAddCallChanged : %b", canAddCall);
+ for (IInCallService inCallService : mInCallServices.values()) {
+ try {
+ inCallService.onCanAddCallChanged(canAddCall);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+ }
+
void onPostDialWait(Call call, String remaining) {
if (!mInCallServices.isEmpty()) {
Log.i(this, "Calling onPostDialWait, remaining = %s", remaining);
@@ -352,6 +365,7 @@
}
}
onAudioStateChanged(null, CallsManager.getInstance().getAudioState());
+ onCanAddCallChanged(CallsManager.getInstance().canAddCall());
} else {
unbind();
}
@@ -431,17 +445,12 @@
int state = call.getState();
int capabilities = call.getCallCapabilities();
- if (!CallsManager.getInstance().isOnlyTopLevelCall(call) || state == CallState.DIALING) {
- capabilities = PhoneCapabilities.remove(capabilities, PhoneCapabilities.ADD_CALL);
- }
-
if (call.isRespondViaSmsCapable()) {
capabilities |= PhoneCapabilities.RESPOND_VIA_TEXT;
}
if (call.isEmergencyCall()) {
capabilities = PhoneCapabilities.remove(capabilities, PhoneCapabilities.MUTE);
- capabilities = PhoneCapabilities.remove(capabilities, PhoneCapabilities.ADD_CALL);
}
if (state == CallState.DIALING) {
diff --git a/tests/src/com/android/server/telecom/testapps/TestConnectionService.java b/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
index 389373f..a474213 100644
--- a/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -135,7 +135,6 @@
// Assume all calls are video capable.
int capabilities = getCallCapabilities();
capabilities |= PhoneCapabilities.SUPPORTS_VT_LOCAL;
- capabilities |= PhoneCapabilities.ADD_CALL;
capabilities |= PhoneCapabilities.MUTE;
capabilities |= PhoneCapabilities.SUPPORT_HOLD;
capabilities |= PhoneCapabilities.HOLD;