am 686a9505: Merge "Update switch call and accept call." into gingerbread

Merge commit '686a95055896c221c62fe7f4c3dda137809df91e' into gingerbread-plus-aosp

* commit '686a95055896c221c62fe7f4c3dda137809df91e':
  Update switch call and accept call.
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 3658961..7829006 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1692,6 +1692,15 @@
     }
 
     /**
+     * @hide
+     * @param number
+     * @return true if number contains @
+     */
+    public static boolean isUriNumber(String number) {
+        return number != null && number.contains("@");
+    }
+
+    /**
      * This function handles the plus code conversion within NANP CDMA network
      * If the number format is
      * 1)+1NANP,remove +,
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 4dc1991..819cfbe 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -21,12 +21,18 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.RegistrantList;
+import android.util.Log;
+
 import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+
+
 /**
  * @hide
  *
@@ -46,6 +52,9 @@
  */
 public final class CallManager {
 
+    private static final String LOG_TAG ="GSM";
+    private static final boolean LOCAL_DEBUG = true;
+
     private static final int EVENT_DISCONNECT = 100;
     private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101;
     private static final int EVENT_NEW_RINGING_CONNECTION = 102;
@@ -180,7 +189,7 @@
     public Phone.State getState() {
         Phone.State s = Phone.State.IDLE;
 
-        for(Phone phone : mPhones) {
+        for (Phone phone : mPhones) {
             if (phone.getState() == Phone.State.RINGING) {
                 return Phone.State.RINGING;
             } else if (phone.getState() == Phone.State.OFFHOOK) {
@@ -191,6 +200,41 @@
     }
 
     /**
+     * @return the service state of CallManager, which represents the
+     * highest priority state of all the service states of phones
+     *
+     * The priority is defined as
+     *
+     * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF
+     *
+     */
+
+    public int getServiceState() {
+        int resultState = ServiceState.STATE_OUT_OF_SERVICE;
+
+        for (Phone phone : mPhones) {
+            int serviceState = phone.getServiceState().getState();
+            if (serviceState == ServiceState.STATE_IN_SERVICE) {
+                // IN_SERVICE has the highest priority
+                resultState = serviceState;
+                break;
+            } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
+                // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF
+                // Note: EMERGENCY_ONLY is not in use at this moment
+                if ( resultState == ServiceState.STATE_EMERGENCY_ONLY ||
+                        resultState == ServiceState.STATE_POWER_OFF) {
+                    resultState = serviceState;
+                }
+            } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
+                if (resultState == ServiceState.STATE_POWER_OFF) {
+                    resultState = serviceState;
+                }
+            }
+        }
+        return resultState;
+    }
+
+    /**
      * Register phone to CallManager
      * @param phone
      * @return true if register successfully
@@ -211,6 +255,34 @@
     }
 
     /**
+     * return the default phone or null if no phone available
+     */
+    public Phone getDefaultPhone() {
+        return mDefaultPhone;
+    }
+
+    /**
+     * @return the phone associated with the foreground call
+     */
+    public Phone getFgPhone() {
+        return getActiveFgCall().getPhone();
+    }
+
+    /**
+     * @return the phone associated with the background call
+     */
+    public Phone getBgPhone() {
+        return getFirstActiveBgCall().getPhone();
+    }
+
+    /**
+     * @return the phone associated with the ringing call
+     */
+    public Phone getRingingPhone() {
+        return getFirstActiveRingingCall().getPhone();
+    }
+
+    /**
      * unregister phone from CallManager
      * @param phone
      */
@@ -291,9 +363,13 @@
 
         if ( hasActiveFgCall() ) {
             Phone activePhone = getActiveFgCall().getPhone();
-            boolean hasBgCall = activePhone.getBackgroundCall().isIdle();
+            boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle());
             boolean sameChannel = (activePhone == ringingPhone);
 
+            if (LOCAL_DEBUG) {
+                Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel);
+            }
+
             if (sameChannel && hasBgCall) {
                 getActiveFgCall().hangup();
             } else if (!sameChannel && !hasBgCall) {
@@ -322,14 +398,21 @@
     }
 
     /**
-     * Places any active calls on hold, and makes any held calls
-     *  active. Switch occurs asynchronously and may fail.
+     * Places active call on hold, and makes held call active.
+     * Switch occurs asynchronously and may fail.
+     *
+     * There are 4 scenarios
+     * 1. only active call but no held call, aka, hold
+     * 2. no active call but only held call, aka, unhold
+     * 3. both active and held calls from same phone, aka, swap
+     * 4. active and held calls from different phones, aka, phone swap
+     *
      * Final notification occurs via
      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPreciseCallStateChanged()}.
      *
      * @exception CallStateException if active call is ringing, waiting, or
-     * dialing/alerting, or heldCall can�t be active.
+     * dialing/alerting, or heldCall can't be active.
      * In these cases, this operation may not be performed.
      */
     public void switchHoldingAndActive(Call heldCall) throws CallStateException {
@@ -344,11 +427,13 @@
             heldPhone = heldCall.getPhone();
         }
 
-        if (activePhone != heldPhone) {
+        if (activePhone != null) {
             activePhone.switchHoldingAndActive();
         }
 
-        heldPhone.switchHoldingAndActive();
+        if (heldPhone != null && heldPhone != activePhone) {
+            heldPhone.switchHoldingAndActive();
+        }
     }
 
     /**
@@ -398,6 +483,24 @@
      * handled asynchronously.
      */
     public Connection dial(Phone phone, String dialString) throws CallStateException {
+        if ( hasActiveFgCall() ) {
+            Phone activePhone = getActiveFgCall().getPhone();
+            boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
+
+            if (LOCAL_DEBUG) {
+                Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + (activePhone != phone));
+            }
+
+            if (activePhone != phone) {
+                if (hasBgCall) {
+                    Log.d(LOG_TAG, "Hangup");
+                    getActiveFgCall().hangup();
+                } else {
+                    Log.d(LOG_TAG, "Switch");
+                    activePhone.switchHoldingAndActive();
+                }
+            }
+        }
         return phone.dial(dialString);
     }
 
@@ -975,7 +1078,7 @@
      * @return list of ringing calls
      */
     public ArrayList<Call> getRingingCalls() {
-        return mBackgroundCalls;
+        return mRingingCalls;
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 23325f6..33f7c9d 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -177,6 +177,7 @@
     static final int PHONE_TYPE_NONE = RILConstants.NO_PHONE;
     static final int PHONE_TYPE_GSM = RILConstants.GSM_PHONE;
     static final int PHONE_TYPE_CDMA = RILConstants.CDMA_PHONE;
+    static final int PHONE_TYPE_SIP = RILConstants.SIP_PHONE;
 
     // Used for preferred network type
     // Note NT_* substitute RILConstants.NETWORK_MODE_* above the Phone
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 71a80e0..888f721 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -79,6 +79,7 @@
     int NO_PHONE = 0;
     int GSM_PHONE = 1;
     int CDMA_PHONE = 2;
+    int SIP_PHONE  = 3;
 
     int CDM_TTY_MODE_DISABLED = 0;
     int CDM_TTY_MODE_ENABLED = 1;