Merge "Add missing break statement." into nyc-mr1-dev
diff --git a/src/com/android/services/telephony/EmergencyCallStateListener.java b/src/com/android/services/telephony/EmergencyCallStateListener.java
index 2346a7f..036872d 100644
--- a/src/com/android/services/telephony/EmergencyCallStateListener.java
+++ b/src/com/android/services/telephony/EmergencyCallStateListener.java
@@ -24,6 +24,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.SubscriptionController;
@@ -159,30 +160,19 @@
             onComplete(true);
             cleanup();
         } else {
-            // The service state changed, but we're still not ready to call yet. (This probably was
-            // the transition from STATE_POWER_OFF to STATE_OUT_OF_SERVICE, which happens
-            // immediately after powering-on the radio.)
-            //
-            // So just keep waiting; we'll probably get to either STATE_IN_SERVICE or
-            // STATE_EMERGENCY_ONLY very shortly. (Or even if that doesn't happen, we'll at least do
-            // another retry when the RETRY_TIMEOUT event fires.)
+            // The service state changed, but we're still not ready to call yet.
             Log.d(this, "onServiceStateChanged: not ready to call yet, keep waiting.");
         }
     }
 
+    /**
+     * We currently only look to make sure that the radio is on before dialing. We should be able to
+     * make emergency calls at any time after the radio has been powered on and isn't in the
+     * UNAVAILABLE state, even if it is reporting the OUT_OF_SERVICE state.
+     */
     private boolean isOkToCall(int serviceState) {
-        // Once we reach either STATE_IN_SERVICE or STATE_EMERGENCY_ONLY, it's finally OK to place
-        // the emergency call.
-        return ((mPhone.getState() == PhoneConstants.State.OFFHOOK)
-                || (serviceState == ServiceState.STATE_IN_SERVICE)
-                || (serviceState == ServiceState.STATE_EMERGENCY_ONLY))
-                // STATE_EMERGENCY_ONLY currently is not used, so we must also check the service
-                // state for emergency only calling.
-                || (serviceState == ServiceState.STATE_OUT_OF_SERVICE &&
-                        mPhone.getServiceState().isEmergencyOnly())
-                // Allow STATE_OUT_OF_SERVICE if we are at the max number of retries.
-                || (mNumRetriesSoFar == MAX_NUM_RETRIES &&
-                        serviceState == ServiceState.STATE_OUT_OF_SERVICE);
+        return (mPhone.getState() == PhoneConstants.State.OFFHOOK) ||
+                mPhone.getServiceStateTracker().isRadioOn();
     }
 
     /**
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 62bbfe2..fcee589 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -571,8 +571,12 @@
 
         mConferenceHost.addConnectionListener(mConferenceHostListener);
         mConferenceHost.addTelephonyConnectionListener(mTelephonyConnectionListener);
-        setState(mConferenceHost.getState());
+        setConnectionCapabilities(applyHostCapabilities(getConnectionCapabilities(),
+                mConferenceHost.getConnectionCapabilities()));
+        setConnectionProperties(applyHostProperties(getConnectionProperties(),
+                mConferenceHost.getConnectionProperties()));
 
+        setState(mConferenceHost.getState());
         updateStatusHints();
     }
 
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 3c9b508..6370dca 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -34,6 +34,7 @@
 import android.telephony.PhoneNumberUtils;
 import android.util.Pair;
 
+import com.android.ims.ImsCall;
 import com.android.ims.ImsCallProfile;
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
@@ -44,6 +45,7 @@
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
 import com.android.phone.PhoneUtils;
 import com.android.phone.R;
 
@@ -165,8 +167,9 @@
                     setVideoState(videoState);
 
                     // A change to the video state of the call can influence whether or not it
-                    // can be part of a conference.
+                    // can be part of a conference and whether another call can be added.
                     refreshConferenceSupported();
+                    refreshDisableAddCall();
                     break;
 
                 case MSG_SET_VIDEO_PROVIDER:
@@ -780,10 +783,10 @@
             extrasToRemove.add(Connection.EXTRA_ANSWERING_DROPS_FG_CALL);
         }
 
-        if (!mOriginalConnection.shouldAllowAddCallDuringVideoCall()) {
-            extrasToPut.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL_DURING_VIDEO_CALL, true);
+        if (shouldSetDisableAddCallExtra()) {
+            extrasToPut.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true);
         } else {
-            extrasToRemove.add(Connection.EXTRA_DISABLE_ADD_CALL_DURING_VIDEO_CALL);
+            extrasToRemove.add(Connection.EXTRA_DISABLE_ADD_CALL);
         }
         putExtras(extrasToPut);
         removeExtras(extrasToRemove);
@@ -808,6 +811,48 @@
         }
     }
 
+    private void refreshDisableAddCall() {
+        if (shouldSetDisableAddCallExtra()) {
+            putExtra(Connection.EXTRA_DISABLE_ADD_CALL, true);
+        } else {
+            removeExtras(Connection.EXTRA_DISABLE_ADD_CALL);
+        }
+    }
+
+    private boolean shouldSetDisableAddCallExtra() {
+        boolean carrierShouldAllowAddCall = mOriginalConnection.shouldAllowAddCallDuringVideoCall();
+        if (carrierShouldAllowAddCall) {
+            return false;
+        }
+        Phone phone = getPhone();
+        if (phone == null) {
+            return false;
+        }
+        boolean isCurrentVideoCall = false;
+        boolean wasVideoCall = false;
+        boolean isWifiCall = false;
+        boolean isVowifiEnabled = false;
+        if (phone instanceof ImsPhone) {
+            ImsPhone imsPhone = (ImsPhone) phone;
+            if (imsPhone.getForegroundCall() != null
+                    && imsPhone.getForegroundCall().getImsCall() != null) {
+                ImsCall call = imsPhone.getForegroundCall().getImsCall();
+                isCurrentVideoCall = call.isVideoCall();
+                wasVideoCall = call.wasVideoCall();
+                isWifiCall = call.isWifiCall();
+            }
+
+            isVowifiEnabled = ((ImsPhoneCallTracker) imsPhone.getCallTracker()).isVowifiEnabled();
+        }
+
+        if (isCurrentVideoCall) {
+            return true;
+        } else if (wasVideoCall && isWifiCall && !isVowifiEnabled) {
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Whether the connection should be treated as an emergency.
      * @return {@code true} if the connection should be treated as an emergency call based