Cdma Outgoing 3way call support.
Cdma outgoing calls when a call already exists are special because
like normal cdma calls there is no "dialing" state. There is also
no indication that the caller answered the phone so we have to make
guesses as to the state of the world.
This changes leverages code that already established these assumptions
can have those places call directly into CallModeler so that it can
translate those assumptions into Call objects that the UI can
understand.
Changes:
- Add concept of a generic conference call to be used for cdma
conference calls which are very limited in nature.
- Notify CallModeler when we see an outgoing 3way call so that it
can fake it as a "dialing" call until we are notified that it
has "connected". This gives used the impression of a dialing state
on cdma devices which do not have this state.
- fix CallModeler.getFullList() which previously changes model state.
bug:10769004
Change-Id: Iec5fb47fdcd1574c86120ec0fbb38911d54c7b0e
diff --git a/src/com/android/phone/CallController.java b/src/com/android/phone/CallController.java
index 44de433..2cceed0 100644
--- a/src/com/android/phone/CallController.java
+++ b/src/com/android/phone/CallController.java
@@ -144,8 +144,7 @@
// Reset the mThreeWayCallOrigStateDialing state
mApp.cdmaPhoneCallState.setThreeWayCallOrigState(false);
- // Refresh the in-call UI (based on the current ongoing call)
- mApp.updateInCallScreen();
+ mApp.getCallModeler().setCdmaOutgoing3WayCall(null);
}
break;
diff --git a/src/com/android/phone/CallModeler.java b/src/com/android/phone/CallModeler.java
index f3e0d36..7af2416 100644
--- a/src/com/android/phone/CallModeler.java
+++ b/src/com/android/phone/CallModeler.java
@@ -35,13 +35,14 @@
import com.android.services.telephony.common.Call.Capabilities;
import com.android.services.telephony.common.Call.State;
-import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
@@ -92,6 +93,7 @@
private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
private RejectWithTextMessageManager mRejectWithTextMessageManager;
private Connection mCdmaIncomingConnection;
+ private Connection mCdmaOutgoingConnection;
public CallModeler(CallStateMonitor callStateMonitor, CallManager callManager,
RejectWithTextMessageManager rejectWithTextMessageManager,
@@ -133,9 +135,11 @@
}
public List<Call> getFullList() {
- final List<Call> retval = Lists.newArrayList();
- doUpdate(true, retval);
- return retval;
+ final List<Call> calls =
+ Lists.newArrayListWithCapacity(mCallMap.size() + mConfCallMap.size());
+ calls.addAll(mCallMap.values());
+ calls.addAll(mConfCallMap.values());
+ return calls;
}
public CallResult getCallWithId(int callId) {
@@ -192,6 +196,24 @@
}
}
+ /**
+ * CDMA Calls have no sense of "dialing" state. For outgoing calls 3way calls we want to
+ * mimick this state so that the the UI can notify the user that there is a "dialing"
+ * call.
+ */
+ public void setCdmaOutgoing3WayCall(Connection connection) {
+ boolean wasSet = mCdmaOutgoingConnection != null;
+
+ mCdmaOutgoingConnection = connection;
+
+ // If we reset the connection, that mean we can now tell the user that the call is actually
+ // part of the conference call and move it out of the dialing state. To do this, issue a
+ // new update completely.
+ if (wasSet && mCdmaOutgoingConnection == null) {
+ onPhoneStateChanged(null);
+ }
+ }
+
private boolean hasLiveCallInternal(HashMap<Connection, Call> map) {
for (Call call : map.values()) {
final int state = call.getState();
@@ -547,7 +569,7 @@
/**
* !!! Uses values from connection and call collected above so this part must be last !!!
*/
- final int newCapabilities = getCapabilitiesFor(connection, call);
+ final int newCapabilities = getCapabilitiesFor(connection, call, isForConference);
if (call.getCapabilities() != newCapabilities) {
call.setCapabilities(newCapabilities);
changed = true;
@@ -559,7 +581,7 @@
/**
* Returns a mask of capabilities for the connection such as merge, hold, etc.
*/
- private int getCapabilitiesFor(Connection connection, Call call) {
+ private int getCapabilitiesFor(Connection connection, Call call, boolean isForConference) {
final boolean callIsActive = (call.getState() == Call.State.ACTIVE);
final Phone phone = connection.getCall().getPhone();
@@ -571,6 +593,8 @@
final boolean supportHold = PhoneUtils.okToSupportHold(mCallManager);
final boolean canHold = PhoneUtils.okToHoldCall(mCallManager);
+ final boolean genericConf = isForConference &&
+ (connection.getCall().getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA);
// only applies to active calls
if (callIsActive) {
@@ -627,6 +651,9 @@
if (canMute) {
retval |= Capabilities.MUTE;
}
+ if (genericConf) {
+ retval |= Capabilities.GENERIC_CONFERENCE;
+ }
return retval;
}
@@ -640,7 +667,10 @@
if (connection.getCall() != null && connection.getCall().isMultiparty()) {
int count = 0;
for (Connection currConn : connection.getCall().getConnections()) {
- if (currConn.isAlive()) {
+
+ // Only count connections which are alive and never cound the special
+ // "dialing" 3way call for CDMA calls.
+ if (currConn.isAlive() && currConn != mCdmaOutgoingConnection) {
count++;
if (count >= 2) {
return true;
@@ -653,6 +683,11 @@
private int translateStateFromTelephony(Connection connection, boolean isForConference) {
+ // For the "fake" outgoing CDMA call, we need to always treat it as an outgoing call.
+ if (mCdmaOutgoingConnection == connection) {
+ return State.DIALING;
+ }
+
int retval = State.IDLE;
switch (connection.getState()) {
case ACTIVE:
@@ -680,7 +715,6 @@
// If we are dealing with a potential child call (not the parent conference call),
// the check to see if we have to set the state to CONFERENCED.
if (!isForConference) {
-
// if the connection is part of a multiparty call, and it is live,
// annotate it with CONFERENCED state instead.
if (isPartOfLiveConferenceCall(connection) && connection.isAlive()) {
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 214402d..49a3427 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -677,6 +677,10 @@
return audioRouter;
}
+ /* package */ CallModeler getCallModeler() {
+ return callModeler;
+ }
+
/**
* Returns an Intent that can be used to go to the "Call log"
* UI (aka CallLogActivity) in the Contacts app.
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index bb858b0..c3abd9f 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -548,7 +548,8 @@
* </pre>
* @param app The phone instance.
*/
- private static void updateCdmaCallStateOnNewOutgoingCall(PhoneGlobals app) {
+ private static void updateCdmaCallStateOnNewOutgoingCall(PhoneGlobals app,
+ Connection connection) {
if (app.cdmaPhoneCallState.getCurrentCallState() ==
CdmaPhoneCallState.PhoneCallState.IDLE) {
// This is the first outgoing call. Set the Phone Call State to ACTIVE
@@ -558,6 +559,8 @@
// This is the second outgoing call. Set the Phone Call State to 3WAY
app.cdmaPhoneCallState.setCurrentCallState(
CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE);
+
+ app.getCallModeler().setCdmaOutgoing3WayCall(connection);
}
}
@@ -671,7 +674,7 @@
}
} else {
if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
- updateCdmaCallStateOnNewOutgoingCall(app);
+ updateCdmaCallStateOnNewOutgoingCall(app, connection);
}
// Clean up the number to be displayed.