Revise phone app to accept new PHONE_TYPE_SIP phone type.

Change-Id: Ib5d930b64a95a86822669367cb6f69359a04bfb6
diff --git a/src/com/android/phone/CallCard.java b/src/com/android/phone/CallCard.java
index 4bc51a0..d85e531 100755
--- a/src/com/android/phone/CallCard.java
+++ b/src/com/android/phone/CallCard.java
@@ -291,7 +291,8 @@
                 // we need to clean up the background call area.
                 displayOnHoldCallStatus(cm, bgCall);
             }
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             displayOnHoldCallStatus(cm, bgCall);
         }
     }
@@ -409,7 +410,7 @@
 
         if (PhoneUtils.isConferenceCall(call)) {
             // Update onscreen info for a conference call.
-            updateDisplayForConference();
+            updateDisplayForConference(call);
         } else {
             // Update onscreen info for a regular call (which presumably
             // has only one connection.)
@@ -417,7 +418,8 @@
             int phoneType = call.getPhone().getPhoneType();
             if (phoneType == Phone.PHONE_TYPE_CDMA) {
                 conn = call.getLatestConnection();
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                  || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 conn = call.getEarliestConnection();
             } else {
                 throw new IllegalStateException("Unexpected phone type: " + phoneType);
@@ -548,10 +550,11 @@
             if (DBG) log("callerinfo query complete, updating ui from displayMainCallStatus()");
             Call call = (Call) cookie;
             Connection conn = null;
-            int phoneType = mApplication.phone.getPhoneType();
+            int phoneType = call.getPhone().getPhoneType();
             if (phoneType == Phone.PHONE_TYPE_CDMA) {
                 conn = call.getLatestConnection();
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                  || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 conn = call.getEarliestConnection();
             } else {
                 throw new IllegalStateException("Unexpected phone type: " + phoneType);
@@ -609,14 +612,15 @@
         // need to be set.)
 
         String cardTitle;
-        int phoneType = mApplication.phone.getPhoneType();
+        int phoneType = phone.getPhoneType();
         if (phoneType == Phone.PHONE_TYPE_CDMA) {
             if (!PhoneApp.getInstance().notifier.getIsCdmaRedialCall()) {
                 cardTitle = getTitleForCallCard(call);  // Normal "foreground" call card
             } else {
                 cardTitle = getContext().getString(R.string.card_title_redialing);
             }
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             cardTitle = getTitleForCallCard(call);
         } else {
             throw new IllegalStateException("Unexpected phone type: " + phoneType);
@@ -643,7 +647,8 @@
                         // Normal "ongoing call" state; don't use any "title" at all.
                         clearUpperTitle();
                     }
-                } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+                } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                        || (phoneType == Phone.PHONE_TYPE_SIP)) {
                     // While in the DISCONNECTING state we display a
                     // "Hanging up" message in order to make the UI feel more
                     // responsive.  (In GSM it's normal to see a delay of a
@@ -749,14 +754,15 @@
             case ACTIVE:
                 // Title is "Call in progress".  (Note this appears in the
                 // "lower title" area of the CallCard.)
-                int phoneType = mApplication.phone.getPhoneType();
+                int phoneType = call.getPhone().getPhoneType();
                 if (phoneType == Phone.PHONE_TYPE_CDMA) {
                     if (mApplication.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) {
                         retVal = context.getString(R.string.card_title_dialing);
                     } else {
                         retVal = context.getString(R.string.card_title_in_progress);
                     }
-                } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+                } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                        || (phoneType == Phone.PHONE_TYPE_SIP)) {
                     retVal = context.getString(R.string.card_title_in_progress);
                 } else {
                     throw new IllegalStateException("Unexpected phone type: " + phoneType);
@@ -1146,10 +1152,10 @@
      * If the current call has only a single connection, use
      * updateDisplayForPerson() instead.
      */
-    private void updateDisplayForConference() {
+    private void updateDisplayForConference(Call call) {
         if (DBG) log("updateDisplayForConference()...");
 
-        int phoneType = mApplication.phone.getPhoneType();
+        int phoneType = call.getPhone().getPhoneType();
         if (phoneType == Phone.PHONE_TYPE_CDMA) {
             // This state corresponds to both 3-Way merged call and
             // Call Waiting accepted call.
@@ -1159,7 +1165,8 @@
             // which caller party he is talking to.
             showImage(mPhoto, R.drawable.picture_dialing);
             mName.setText(R.string.card_title_in_call);
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             if (mInCallScreen.isTouchUiEnabled()) {
                 // Display the "manage conference" button in place of the photo.
                 mManageConferencePhotoButton.setVisibility(View.VISIBLE);
@@ -1258,10 +1265,11 @@
                 CallerInfo ci = null;
                 {
                     Connection conn = null;
-                    int phoneType = mApplication.phone.getPhoneType();
+                    int phoneType = call.getPhone().getPhoneType();
                     if (phoneType == Phone.PHONE_TYPE_CDMA) {
                         conn = call.getLatestConnection();
-                    } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+                    } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                            || (phoneType == Phone.PHONE_TYPE_SIP)) {
                         conn = call.getEarliestConnection();
                     } else {
                         throw new IllegalStateException("Unexpected phone type: " + phoneType);
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 2b0ad52..a3274e1 100755
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -145,13 +145,10 @@
     private static final int EMERGENCY_TONE_VIBRATE = 2;
 
     private PhoneApp mApplication;
-    private Phone mPhone;
     private CallManager mCM;
     private Ringer mRinger;
     private BluetoothHandsfree mBluetoothHandsfree;
     private CallLogAsync mCallLog;
-    // TODO get rid of mPhoneContext and replace it with mApplcation's
-    private Context mPhoneContext;
     private boolean mSilentRingerRequested;
 
     // ToneGenerator instance for playing SignalInfo tones
@@ -181,14 +178,10 @@
     public CallNotifier(PhoneApp app, Phone phone, Ringer ringer,
                         BluetoothHandsfree btMgr, CallLogAsync callLog) {
         mApplication = app;
-        mPhone = phone;
         mCM = app.mCM;
         mCallLog = callLog;
-        // TODO
-        //replace this with mApplication context while finally get rid of mPhone
-        mPhoneContext = mPhone.getContext();
 
-        mAudioManager = (AudioManager) mPhoneContext.getSystemService(Context.AUDIO_SERVICE);
+        mAudioManager = (AudioManager) mApplication.getSystemService(Context.AUDIO_SERVICE);
 
         registerForNotifications();
 
@@ -267,7 +260,7 @@
                 break;
 
             case PHONE_MWI_CHANGED:
-                onMwiChanged(mPhone.getMessageWaitingIndicator());
+                onMwiChanged(mApplication.phone.getMessageWaitingIndicator());
                 break;
 
             case PHONE_BATTERY_LOW:
@@ -372,9 +365,9 @@
         Phone phone = ringing.getPhone();
 
         // Incoming calls are totally ignored if the device isn't provisioned yet
-        boolean provisioned = Settings.Secure.getInt(mPhoneContext.getContentResolver(),
+        boolean provisioned = Settings.Secure.getInt(mApplication.getContentResolver(),
             Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
-        if (!provisioned && !PhoneUtils.isPhoneInEcm(mPhone)) {
+        if (!provisioned && !PhoneUtils.isPhoneInEcm(phone)) {
             Log.i(LOG_TAG, "CallNotifier: rejecting incoming call: not provisioned / ECM");
             // Send the caller straight to voicemail, just like
             // "rejecting" an incoming call.
@@ -418,7 +411,7 @@
         }
 
         // Stop any signalInfo tone being played on receiving a Call
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+        if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
             stopSignalInfoTone();
         }
 
@@ -512,7 +505,7 @@
 
             // query the callerinfo to try to get the ringer.
             PhoneUtils.CallerInfoToken cit = PhoneUtils.startGetCallerInfo(
-                    mPhoneContext, c, this, this);
+                    mApplication, c, this, this);
 
             // if this has already been queried then just ring, otherwise
             // we wait for the alloted time before ringing.
@@ -701,8 +694,9 @@
         NotificationMgr.getDefault().getStatusBarMgr()
                 .enableNotificationAlerts(state == Phone.State.IDLE);
 
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            if ((mPhone.getForegroundCall().getState() == Call.State.ACTIVE)
+        Phone fgPhone = mCM.getFgPhone();
+        if (fgPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+            if ((fgPhone.getForegroundCall().getState() == Call.State.ACTIVE)
                     && ((mPreviousCdmaCallState == Call.State.DIALING)
                     ||  (mPreviousCdmaCallState == Call.State.ALERTING))) {
                 if (mIsCdmaRedialCall) {
@@ -712,7 +706,7 @@
                 // Stop any signal info tone when call moves to ACTIVE state
                 stopSignalInfoTone();
             }
-            mPreviousCdmaCallState = mPhone.getForegroundCall().getState();
+            mPreviousCdmaCallState = fgPhone.getForegroundCall().getState();
         }
 
         // Have the PhoneApp recompute its mShowBluetoothIndication
@@ -758,18 +752,18 @@
             NotificationMgr.getDefault().updateInCallNotification();
         }
 
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            Connection c = mPhone.getForegroundCall().getLatestConnection();
+        if (fgPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+            Connection c = fgPhone.getForegroundCall().getLatestConnection();
             if ((c != null) && (PhoneNumberUtils.isEmergencyNumber(c.getAddress()))) {
                 if (VDBG) log("onPhoneStateChanged: it is an emergency call.");
-                Call.State callState = mPhone.getForegroundCall().getState();
+                Call.State callState = fgPhone.getForegroundCall().getState();
                 if (mEmergencyTonePlayerVibrator == null) {
                     mEmergencyTonePlayerVibrator = new EmergencyTonePlayerVibrator();
                 }
 
                 if (callState == Call.State.DIALING || callState == Call.State.ALERTING) {
                     mIsEmergencyToneOn = Settings.System.getInt(
-                            mPhoneContext.getContentResolver(),
+                            mApplication.getContentResolver(),
                             Settings.System.EMERGENCY_TONE, EMERGENCY_TONE_OFF);
                     if (mIsEmergencyToneOn != EMERGENCY_TONE_OFF &&
                         mCurrentEmergencyToneState == EMERGENCY_TONE_OFF) {
@@ -787,7 +781,8 @@
             }
         }
 
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_GSM) {
+        if ((fgPhone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+                || (fgPhone.getPhoneType() == Phone.PHONE_TYPE_SIP)) {
             Call.State callState = mCM.getActiveFgCallState();
             if (!callState.isDialing()) {
                 // If call get activated or disconnected before the ringback
@@ -840,7 +835,7 @@
         mCM.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
         mCM.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
 
-        if (TelephonyCapabilities.supportsOtasp(mPhone)) {
+        if (TelephonyCapabilities.supportsOtasp(mApplication.phone)) {
             mCM.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);
         }
         mCM.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
@@ -884,7 +879,7 @@
                 // send directly to voicemail.
                 if (ci.shouldSendToVoicemail) {
                     if (DBG) log("send to voicemail flag detected. hanging up.");
-                    PhoneUtils.hangupRingingCall(mPhone.getRingingCall());
+                    PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
                     return;
                 }
 
@@ -903,14 +898,22 @@
     private void onDisconnect(AsyncResult r) {
         if (VDBG) log("onDisconnect()...  CallManager state: " + mCM.getState());
 
+        Connection c = (Connection) r.result;
+        if (DBG && c != null) {
+            log("- onDisconnect: cause = " + c.getDisconnectCause()
+                + ", incoming = " + c.isIncoming()
+                + ", date = " + c.getCreateTime());
+        }
+
+
         mCdmaVoicePrivacyState = false;
         int autoretrySetting = 0;
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            autoretrySetting = android.provider.Settings.System.getInt(mPhoneContext.
+        if ((c != null) && (c.getCall().getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA)) {
+            autoretrySetting = android.provider.Settings.System.getInt(mApplication.
                     getContentResolver(),android.provider.Settings.System.CALL_AUTO_RETRY, 0);
         }
 
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+        if ((c != null) && (c.getCall().getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA)) {
             // Stop any signalInfo tone being played when a call gets ended
             stopSignalInfoTone();
 
@@ -922,13 +925,6 @@
             removeMessages(CALLWAITING_ADDCALL_DISABLE_TIMEOUT);
         }
 
-        Connection c = (Connection) r.result;
-        if (DBG && c != null) {
-            log("- onDisconnect: cause = " + c.getDisconnectCause()
-                + ", incoming = " + c.isIncoming()
-                + ", date = " + c.getCreateTime());
-        }
-
         // Stop the ringer if it was ringing (for an incoming call that
         // either disconnected by itself, or was rejected by the user.)
         //
@@ -942,8 +938,9 @@
         // higher preference. At this time framework sends a disconnect for the Out going
         // call connection hence we should *not* be stopping the ringer being played for
         // the Incoming Call
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            if (PhoneUtils.isRealIncomingCall(mPhone.getRingingCall().getState())) {
+        Call ringingCall = mCM.getFirstActiveRingingCall();
+        if (ringingCall.getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+            if (PhoneUtils.isRealIncomingCall(ringingCall.getState())) {
                 // Also we need to take off the "In Call" icon from the Notification
                 // area as the Out going Call never got connected
                 if (DBG) log("cancelCallInProgressNotification()... (onDisconnect)");
@@ -1049,6 +1046,7 @@
             final long date = c.getCreateTime();
             final long duration = c.getDurationMillis();
             final Connection.DisconnectCause cause = c.getDisconnectCause();
+            final Phone phone = c.getCall().getPhone();
 
             // Set the "type" to be displayed in the call log (see constants in CallLog.Calls)
             final int callLogType;
@@ -1074,7 +1072,7 @@
                 // For international calls, 011 needs to be logged as +
                 final int presentation = getPresentation(c, ci);
 
-                if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+                if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
                     if ((PhoneNumberUtils.isEmergencyNumber(number))
                             && (mCurrentEmergencyToneState != EMERGENCY_TONE_OFF)) {
                         if (mEmergencyTonePlayerVibrator != null) {
@@ -1089,18 +1087,18 @@
                 // (ugly) when we actually mean carrier X.
                 // TODO: Clean this up and come up with a unified strategy.
                 final boolean shouldNotlogEmergencyNumber =
-                        (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+                        (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
 
                 // Don't call isOtaSpNumber on GSM phones.
-                final boolean isOtaNumber = (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA)
-                        && mPhone.isOtaSpNumber(number);
+                final boolean isOtaNumber = (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA)
+                        && phone.isOtaSpNumber(number);
                 final boolean isEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(number);
 
                 // Don't put OTA or CDMA Emergency calls into call log
                 if (!(isOtaNumber || isEmergencyNumber && shouldNotlogEmergencyNumber)) {
                     CallLogAsync.AddCallArgs args =
                             new CallLogAsync.AddCallArgs(
-                                mPhoneContext, ci, logNumber, presentation,
+                                mApplication, ci, logNumber, presentation,
                                 callLogType, date, duration);
 
                     mCallLog.addCall(args);
@@ -1159,7 +1157,7 @@
                     if (autoretrySetting == InCallScreen.AUTO_RETRY_ON) {
                         // TODO: (Moto): The contact reference data may need to be stored and use
                         // here when redialing a call. For now, pass in NULL as the URI parameter.
-                        PhoneUtils.placeCall(mPhone, number, null);
+                        PhoneUtils.placeCall(phone, number, null);
                         mIsCdmaRedialCall = true;
                     } else {
                         mIsCdmaRedialCall = false;
@@ -1183,7 +1181,7 @@
 
         // call turnOnSpeaker() with state=false and store=true even if speaker
         // is already off to reset user requested speaker state.
-        PhoneUtils.turnOnSpeaker(mPhoneContext, false, true);
+        PhoneUtils.turnOnSpeaker(mApplication, false, true);
 
         PhoneUtils.setAudioMode(mCM);
     }
@@ -1305,6 +1303,7 @@
             int toneType = 0;  // passed to ToneGenerator.startTone()
             int toneVolume;  // passed to the ToneGenerator constructor
             int toneLengthMillis;
+            int phoneType = mCM.getFgPhone().getPhoneType();
 
             switch (mToneId) {
                 case TONE_CALL_WAITING:
@@ -1314,12 +1313,12 @@
                     toneLengthMillis = Integer.MAX_VALUE - TONE_TIMEOUT_BUFFER;
                     break;
                 case TONE_BUSY:
-                    int phoneType = mPhone.getPhoneType();
                     if (phoneType == Phone.PHONE_TYPE_CDMA) {
                         toneType = ToneGenerator.TONE_CDMA_NETWORK_BUSY_ONE_SHOT;
                         toneVolume = TONE_RELATIVE_VOLUME_LOPRI;
                         toneLengthMillis = 1000;
-                    } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+                    } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                            || (phoneType == Phone.PHONE_TYPE_SIP)) {
                         toneType = ToneGenerator.TONE_SUP_BUSY;
                         toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
                         toneLengthMillis = 4000;
@@ -1436,7 +1435,6 @@
             boolean okToPlayTone = false;
 
             if (toneGenerator != null) {
-                int phoneType = mPhone.getPhoneType();
                 int ringerMode = mAudioManager.getRingerMode();
                 if (phoneType == Phone.PHONE_TYPE_CDMA) {
                     if (toneType == ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD) {
@@ -1706,14 +1704,14 @@
                 // Do final CNAP modifications of logNumber prior to logging [mimicking
                 // onDisconnect()]
                 final String logNumber = PhoneUtils.modifyForSpecialCnapCases(
-                        mPhoneContext, ci, number, presentation);
+                        mApplication, ci, number, presentation);
                 final int newPresentation = (ci != null) ? ci.numberPresentation : presentation;
                 if (DBG) log("- onCdmaCallWaitingReject(): logNumber set to: " + logNumber
                         + ", newPresentation value is: " + newPresentation);
 
                 CallLogAsync.AddCallArgs args =
                         new CallLogAsync.AddCallArgs(
-                            mPhoneContext, ci, logNumber, presentation,
+                            mApplication, ci, logNumber, presentation,
                             callLogType, date, duration);
 
                 mCallLog.addCall(args);
@@ -1777,11 +1775,11 @@
                 String name = ci.name;
                 String number = ci.phoneNumber;
                 if (ci.numberPresentation == Connection.PRESENTATION_RESTRICTED) {
-                    name = mPhoneContext.getString(R.string.private_num);
+                    name = mApplication.getString(R.string.private_num);
                 } else if (ci.numberPresentation != Connection.PRESENTATION_ALLOWED) {
-                    name = mPhoneContext.getString(R.string.unknown);
+                    name = mApplication.getString(R.string.unknown);
                 } else {
-                    number = PhoneUtils.modifyForSpecialCnapCases(mPhoneContext,
+                    number = PhoneUtils.modifyForSpecialCnapCases(mApplication,
                             ci, number, ci.numberPresentation);
                 }
                 NotificationMgr.getDefault().notifyMissedCall(name, number,
@@ -1913,7 +1911,7 @@
             // from the connection.
             if (null == callerInfo || TextUtils.isEmpty(callerInfo.phoneNumber) ||
                 callerInfo.isEmergencyNumber() || callerInfo.isVoiceMailNumber()) {
-                if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+                if (conn.getCall().getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA) {
                     // In cdma getAddress() is not always equals to getOrigDialString().
                     number = conn.getOrigDialString();
                 } else {
@@ -1930,7 +1928,7 @@
             int presentation = conn.getNumberPresentation();
 
             // Do final CNAP modifications.
-            number = PhoneUtils.modifyForSpecialCnapCases(mPhoneContext, callerInfo,
+            number = PhoneUtils.modifyForSpecialCnapCases(mApplication, callerInfo,
                                                           number, presentation);
             if (!PhoneNumberUtils.isUriNumber(number)) {
                 number = PhoneNumberUtils.stripSeparators(number);
diff --git a/src/com/android/phone/InCallMenu.java b/src/com/android/phone/InCallMenu.java
index 2266121..7f43dc4 100644
--- a/src/com/android/phone/InCallMenu.java
+++ b/src/com/android/phone/InCallMenu.java
@@ -17,6 +17,7 @@
 package com.android.phone;
 
 import android.content.Context;
+import android.net.sip.SipManager;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import com.android.internal.telephony.Call;
@@ -214,9 +215,11 @@
         // This usually has "Show/Hide dialpad", but that gets replaced by
         // "Manage conference" if a conference call is active.
         PhoneApp app = PhoneApp.getInstance();
-        // As managing conference is only valid for GSM and not for CDMA
+        // As managing conference is valid for SIP, we always include it
+        // when SIP VOIP feature is present.
         int phoneType = app.phone.getPhoneType();
-        if (phoneType == Phone.PHONE_TYPE_GSM) {
+        if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || SipManager.isVoipSupported(app)) {
             mInCallMenuView.addItemView(mManageConference, 0);
         }
         mInCallMenuView.addItemView(mShowDialpad, 0);
@@ -234,12 +237,12 @@
         if (phoneType == Phone.PHONE_TYPE_CDMA) {
             mInCallMenuView.addItemView(mAnswer, 2);
             mInCallMenuView.addItemView(mIgnore, 2);
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        }
+        if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || SipManager.isVoipSupported(app)) {
             mInCallMenuView.addItemView(mHold, 2);
             mInCallMenuView.addItemView(mAnswerAndHold, 2);
             mInCallMenuView.addItemView(mAnswerAndEnd, 2);
-        } else {
-            throw new IllegalStateException("Unexpected phone type: " + phoneType);
         }
         mInCallMenuView.addItemView(mMute, 2);
         mInCallMenuView.addItemView(mSpeaker, 2);
@@ -334,7 +337,8 @@
                     // Explicitly remove GSM menu items
                     mAnswerAndHold.setVisible(false);
                     mAnswerAndEnd.setVisible(false);
-                } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+                } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                        || (phoneType == Phone.PHONE_TYPE_SIP)) {
                     mAnswerAndHold.setVisible(true);
                     mAnswerAndHold.setEnabled(true);
                     mAnswerAndEnd.setVisible(true);
diff --git a/src/com/android/phone/InCallScreen.java b/src/com/android/phone/InCallScreen.java
index 2265d1a..b26915b 100755
--- a/src/com/android/phone/InCallScreen.java
+++ b/src/com/android/phone/InCallScreen.java
@@ -1382,7 +1382,8 @@
                 if (DBG) log("answerCall: Switch btwn 2 calls scenario");
                 internalSwapCalls();
             }
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             if (hasRingingCall) {
                 // If an incoming call is ringing, the CALL button is actually
                 // handled by the PhoneWindowManager.  (We do this to make
@@ -2076,6 +2077,8 @@
                         showWaitPromptDialogCDMA(c, postDialStr);
                     } else if (phoneType == Phone.PHONE_TYPE_GSM) {
                         showWaitPromptDialogGSM(c, postDialStr);
+                    } else if (phoneType == Phone.PHONE_TYPE_SIP) {
+                        Log.w(LOG_TAG, "SipPhone doesn't support post dial yet");
                     } else {
                         throw new IllegalStateException("Unexpected phone type: " + phoneType);
                     }
@@ -2397,7 +2400,8 @@
                     postDialStr = fgLatestConnection.getRemainingPostDialString();
                     showWaitPromptDialogCDMA(fgLatestConnection, postDialStr);
                 }
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                    || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 for (Connection cn : fgConnections) {
                     if ((cn != null) && (cn.getPostDialState() == Connection.PostDialState.WAIT)) {
                         postDialStr = cn.getRemainingPostDialString();
@@ -2430,7 +2434,7 @@
         // Make sure the Phone is "in use".  (If not, we shouldn't be on
         // this screen in the first place.)
 
-        int phoneType = mPhone.getPhoneType();
+        int phoneType = mCM.getFgPhone().getPhoneType();
 
         if ((phoneType == Phone.PHONE_TYPE_CDMA)
                 && ((mInCallScreenMode == InCallScreenMode.OTA_NORMAL)
@@ -3560,7 +3564,8 @@
                 // In CDMA this is simply a wrapper around PhoneUtils.answerCall().
                 PhoneUtils.answerCall(ringing);  // Automatically holds the current active call,
                                                 // if there is one
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                    || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 // GSM: this is usually just a wrapper around
                 // PhoneUtils.answerCall(), *but* we also need to do
                 // something special for the "both lines in use" case.
diff --git a/src/com/android/phone/InCallTouchUi.java b/src/com/android/phone/InCallTouchUi.java
index b48e51b..6d70f4a 100644
--- a/src/com/android/phone/InCallTouchUi.java
+++ b/src/com/android/phone/InCallTouchUi.java
@@ -368,7 +368,8 @@
                 // "Merge" option is provided as a button on the top left corner of the screen,
                 // we always set the mMergeButton to GONE
                 mMergeButton.setVisibility(View.GONE);
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                    || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 mMergeButton.setVisibility(View.VISIBLE);
                 mMergeButton.setEnabled(true);
                 mAddButton.setVisibility(View.GONE);
@@ -388,7 +389,8 @@
             mMergeButton.setVisibility(View.GONE);
         }
         if (inCallControlState.canAddCall && inCallControlState.canMerge) {
-            if (phoneType == Phone.PHONE_TYPE_GSM) {
+            if ((phoneType == Phone.PHONE_TYPE_GSM)
+                    || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 // Uh oh, the InCallControlState thinks that "Add" *and* "Merge"
                 // should both be available right now.  This *should* never
                 // happen with GSM, but if it's possible on any
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index c77a6f3..88e5d85 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -370,7 +370,8 @@
                 if (DBG) log("No Ringing call to hangup");
                 return false;
             }
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             // GSM:  Ringing Call and Call waiting, both are hungup by calling
             // hangup(call) function.
             if (DBG) log("hangup ringing call");
@@ -734,7 +735,8 @@
             if (phoneType == Phone.PHONE_TYPE_CDMA) {
                 shouldMute = sConnectionMuteTable.get(
                         phone.getForegroundCall().getLatestConnection());
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                    || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 shouldMute = sConnectionMuteTable.get(c);
             }
             if (shouldMute == null) {
@@ -1276,10 +1278,11 @@
             CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie) {
         PhoneApp app = PhoneApp.getInstance();
         Connection conn = null;
-        int phoneType = app.phone.getPhoneType();
+        int phoneType = call.getPhone().getPhoneType();
         if (phoneType == Phone.PHONE_TYPE_CDMA) {
             conn = call.getLatestConnection();
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             conn = call.getEarliestConnection();
         } else {
             throw new IllegalStateException("Unexpected phone type: " + phoneType);
@@ -1883,7 +1886,8 @@
             int phoneType = phone.getPhoneType();
             if (phoneType == Phone.PHONE_TYPE_CDMA) {
                 answerCall(phone.getRingingCall());
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                    || (phoneType == Phone.PHONE_TYPE_SIP)) {
                 if (hasActiveCall && hasHoldingCall) {
                     if (DBG) log("handleHeadsetHook: ringing (both lines in use) ==> answer!");
                     answerAndEndActive(PhoneApp.getInstance().mCM, phone.getRingingCall());
@@ -1980,8 +1984,8 @@
             PhoneApp app = PhoneApp.getInstance();
             return (app.cdmaPhoneCallState.getCurrentCallState()
                     == CdmaPhoneCallState.PhoneCallState.CONF_CALL);
-        } else if (phoneType == Phone.PHONE_TYPE_GSM ||
-                phoneType == Phone.PHONE_TYPE_SIP) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             // GSM: "Swap" is available if both lines are in use and there's no
             // incoming call.  (Actually we need to verify that the active
             // call really is in the ACTIVE state and the holding call really
@@ -2034,8 +2038,8 @@
             PhoneApp app = PhoneApp.getInstance();
             return ((fgCallState == Call.State.ACTIVE)
                     && (app.cdmaPhoneCallState.getAddCallMenuStateAfterCallWaiting()));
-        } else if (phoneType == Phone.PHONE_TYPE_GSM
-                || phoneType == Phone.PHONE_TYPE_SIP) {
+        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
+                || (phoneType == Phone.PHONE_TYPE_SIP)) {
             // GSM: "Add call" is available only if ALL of the following are true:
             // - There's no incoming ringing call
             // - There's < 2 lines in use
@@ -2321,14 +2325,14 @@
     }
 
     public static Phone getSipPhoneFromUri(CallManager cm, String target) {
-        for (Object obj : cm.getAllPhones()) {
-            if (obj instanceof SipPhone) {
-                String sipUri = ((SipPhone)obj).getSipUri();
+        for (Phone phone : cm.getAllPhones()) {
+            if (phone.getPhoneType() == Phone.PHONE_TYPE_SIP) {
+                String sipUri = ((SipPhone) phone).getSipUri();
                 if (target.equals(sipUri)) {
                     if (DBG) log("- pickPhoneBasedOnNumber:" +
-                            "found SipPhone! obj = " + obj + ", "
-                            + obj.getClass());
-                    return (Phone)obj;
+                            "found SipPhone! obj = " + phone + ", "
+                            + phone.getClass());
+                    return phone;
                 }
             }
         }
diff --git a/src/com/android/phone/SipBroadcastReceiver.java b/src/com/android/phone/SipBroadcastReceiver.java
index ab965c3..648d7a4 100644
--- a/src/com/android/phone/SipBroadcastReceiver.java
+++ b/src/com/android/phone/SipBroadcastReceiver.java
@@ -17,6 +17,7 @@
 package com.android.phone;
 
 import com.android.internal.telephony.CallManager;
+import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.sip.SipPhone;
 import com.android.phone.sip.SipSettings;
@@ -75,9 +76,9 @@
     }
 
     private void removeSipPhone(String sipUri) {
-        for (Object phone : CallManager.getInstance().getAllPhones()) {
-            if (phone instanceof SipPhone) {
-                if (((SipPhone)phone).getSipUri().equals(sipUri)) {
+        for (Phone phone : CallManager.getInstance().getAllPhones()) {
+            if (phone.getPhoneType() == Phone.PHONE_TYPE_SIP) {
+                if (((SipPhone) phone).getSipUri().equals(sipUri)) {
                     CallManager.getInstance().unregisterPhone((SipPhone)phone);
                     return;
                 }
@@ -91,8 +92,8 @@
         try {
             SipAudioCall sipAudioCall = SipManager.getInstance(phoneContext)
                     .takeAudioCall(phoneContext, intent, null, false);
-            for (Object phone : CallManager.getInstance().getAllPhones()) {
-                if (phone instanceof SipPhone) {
+            for (Phone phone : CallManager.getInstance().getAllPhones()) {
+                if (phone.getPhoneType() == Phone.PHONE_TYPE_SIP) {
                    if (((SipPhone) phone).canTake(sipAudioCall)) return;
                 }
             }
diff --git a/src/com/android/phone/TelephonyCapabilities.java b/src/com/android/phone/TelephonyCapabilities.java
index 9267717..53da7f6 100644
--- a/src/com/android/phone/TelephonyCapabilities.java
+++ b/src/com/android/phone/TelephonyCapabilities.java
@@ -54,6 +54,9 @@
             } else {
                 return false;
             }
+        } else if (phoneType == Phone.PHONE_TYPE_SIP) {
+            // TODO: confirm SipPhone supports this
+            return true;
         } else {
             throw new IllegalStateException("Unexpected phone type: " + phoneType);
         }
@@ -167,7 +170,8 @@
      * layer, since it depends on the underlying telephony technology.
      */
     /* package */ static boolean supportsConferenceCallManagement(Phone phone) {
-        return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+        return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+                || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
     }
 
     /**
@@ -182,7 +186,8 @@
      * layer, since it depends on the underlying telephony technology.
      */
     /* package */ static boolean supportsHoldAndUnhold(Phone phone) {
-        return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+        return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+                || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
     }
 
     /**
@@ -203,6 +208,7 @@
      * rather than focusing specifically on call-waiting behavior.
      */
     /* package */ static boolean supportsAnswerAndHold(Phone phone) {
-        return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+        return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+                || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
     }
 }