SIP: duplicate PhoneApp for telephony integration development

Change-Id: I62b01c9f7f93ca3d788222aeb483c3a2dd499117
diff --git a/phone/Android.mk b/phone/Android.mk.sample
similarity index 81%
rename from phone/Android.mk
rename to phone/Android.mk.sample
index c21e7e2..653f77b 100644
--- a/phone/Android.mk
+++ b/phone/Android.mk.sample
@@ -27,13 +27,10 @@
         src/com/android/phone2/INetworkQueryService.aidl \
         src/com/android/phone2/INetworkQueryServiceCallback.aidl
 
-LOCAL_SRC_FILES += $(call all-java-files-under, src2)
-
 LOCAL_PACKAGE_NAME := Phone2
-LOCAL_CERTIFICATE := platform
-LOCAL_STATIC_JAVA_LIBRARIES := android.sip
+#LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
 
-## Build the test package
-#include $(call all-makefiles-under,$(LOCAL_PATH))
+# Build the test package
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/phone/AndroidManifest.xml b/phone/AndroidManifest.xml
index e1679f8..17d1162 100644
--- a/phone/AndroidManifest.xml
+++ b/phone/AndroidManifest.xml
@@ -20,6 +20,7 @@
         android:sharedUserLabel="@string/dialerIconLabel"
 >
 
+    <original-package android:name="com.android.phone2" />
 
     <protected-broadcast android:name="android.intent.action.SERVICE_STATE" />
     <protected-broadcast android:name="android.intent.action.RADIO_TECHNOLOGY" />
@@ -82,7 +83,7 @@
                  android:label="@string/dialerIconLabel"
                  android:icon="@drawable/ic_launcher_phone">
             <provider android:name="IccProvider"
-                      android:authorities="icc2"
+                      android:authorities="icc"
                       android:multiprocess="true"
                       android:readPermission="android.permission.READ_CONTACTS"
                       android:writePermission="android.permission.WRITE_CONTACTS" />
diff --git a/phone/MODULE_LICENSE_APACHE2 b/phone/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/phone/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/phone/NOTICE b/phone/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/phone/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-2008, The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/phone/res/color-finger/end_call_button_text.xml b/phone/res/color-finger/end_call_button_text.xml
new file mode 100644
index 0000000..a570c2b
--- /dev/null
+++ b/phone/res/color-finger/end_call_button_text.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="#80000000"/>
+    <item android:state_focused="true" android:color="#FF000000"/>
+    <item android:state_pressed="true" android:color="#FF000000"/>
+    <item android:state_selected="true" android:color="#FF000000"/>
+    <item android:color="@color/incall_endButtonLabel"/> <!-- not selected -->
+</selector>
+
diff --git a/phone/res/color-finger/in_call_button_text.xml b/phone/res/color-finger/in_call_button_text.xml
new file mode 100644
index 0000000..4a5a4a4
--- /dev/null
+++ b/phone/res/color-finger/in_call_button_text.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="#ff808080"/>
+    <item android:state_focused="true" android:color="#FF000000"/>
+    <item android:state_pressed="true" android:color="#FF000000"/>
+    <item android:state_selected="true" android:color="#FF000000"/>
+    <item android:color="#FFFFFFFF"/> <!-- not selected -->
+</selector>
+
diff --git a/phone/res/drawable-hdpi/ic_btn_back.png b/phone/res/drawable-hdpi/ic_btn_back.png
new file mode 100755
index 0000000..9051cb1
--- /dev/null
+++ b/phone/res/drawable-hdpi/ic_btn_back.png
Binary files differ
diff --git a/phone/res/drawable-hdpi/ic_btn_next.png b/phone/res/drawable-hdpi/ic_btn_next.png
new file mode 100755
index 0000000..ad00a95
--- /dev/null
+++ b/phone/res/drawable-hdpi/ic_btn_next.png
Binary files differ
diff --git a/phone/res/drawable-mdpi/ic_btn_back.png b/phone/res/drawable-mdpi/ic_btn_back.png
new file mode 100644
index 0000000..c9bff4c
--- /dev/null
+++ b/phone/res/drawable-mdpi/ic_btn_back.png
Binary files differ
diff --git a/phone/res/layout-finger/dialpad.xml b/phone/res/layout-finger/dialpad.xml
index 135f0fb..98f8418 100644
--- a/phone/res/layout-finger/dialpad.xml
+++ b/phone/res/layout-finger/dialpad.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<com.android.phone2.ButtonGridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.phone.ButtonGridLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/dialpad"
     android:paddingLeft="7dp"
     android:paddingRight="7dp"
@@ -108,5 +108,5 @@
             android:src="@drawable/dial_num_pound"
             android:background="@drawable/btn_dial"
         />
-</com.android.phone2.ButtonGridLayout>
+</com.android.phone.ButtonGridLayout>
 
diff --git a/phone/res/layout-finger/dtmf_twelve_key_dialer.xml b/phone/res/layout-finger/dtmf_twelve_key_dialer.xml
index b0202e2..e8f971b 100644
--- a/phone/res/layout-finger/dtmf_twelve_key_dialer.xml
+++ b/phone/res/layout-finger/dtmf_twelve_key_dialer.xml
@@ -77,7 +77,7 @@
     </LinearLayout>
 
     <!-- drawer content dialer view -->
-    <com.android.phone2.DTMFTwelveKeyDialerView
+    <com.android.phone.DTMFTwelveKeyDialerView
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/dtmf_dialer"
         android:layout_width="match_parent"
@@ -113,6 +113,6 @@
             android:layout_width="match_parent"
             android:layout_weight="1"/>
 
-    </com.android.phone2.DTMFTwelveKeyDialerView>
+    </com.android.phone.DTMFTwelveKeyDialerView>
 
 </SlidingDrawer>
diff --git a/phone/res/layout-finger/non_drawer_dialpad.xml b/phone/res/layout-finger/non_drawer_dialpad.xml
index b90480d..fe804e8 100644
--- a/phone/res/layout-finger/non_drawer_dialpad.xml
+++ b/phone/res/layout-finger/non_drawer_dialpad.xml
@@ -22,7 +22,7 @@
      dtmf_twelve_key_dialer.xml and dialpad.xml, but in a more
      compact layout, and without the SlidingDrawer container.
      -->
-<com.android.phone2.DTMFTwelveKeyDialerView
+<com.android.phone.DTMFTwelveKeyDialerView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/non_drawer_dtmf_dialer"
     android:layout_width="match_parent"
@@ -54,7 +54,7 @@
         android:clickable="false"/>
 
     <!-- The dialpad itself -->
-    <com.android.phone2.ButtonGridLayout
+    <com.android.phone.ButtonGridLayout
         android:id="@+id/dialpad"
         android:paddingLeft="7dp"
         android:paddingRight="7dp"
@@ -147,6 +147,6 @@
                      android:src="@drawable/dial_num_pound"
                      android:background="@drawable/btn_dial_green"
                      />
-    </com.android.phone2.ButtonGridLayout>
+    </com.android.phone.ButtonGridLayout>
 
-</com.android.phone2.DTMFTwelveKeyDialerView>
+</com.android.phone.DTMFTwelveKeyDialerView>
diff --git a/phone/res/layout-long-finger/dialpad.xml b/phone/res/layout-long-finger/dialpad.xml
index 510b0b6..43311ba 100644
--- a/phone/res/layout-long-finger/dialpad.xml
+++ b/phone/res/layout-long-finger/dialpad.xml
@@ -18,7 +18,7 @@
      Tall screen version with taller buttons.
  -->
 
-<com.android.phone2.ButtonGridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.phone.ButtonGridLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/dialpad"
     android:paddingLeft="7dp"
     android:paddingRight="7dp"
@@ -112,5 +112,5 @@
             android:src="@drawable/dial_num_pound"
             android:background="@drawable/btn_dial"
         />
-</com.android.phone2.ButtonGridLayout>
+</com.android.phone.ButtonGridLayout>
 
diff --git a/phone/res/layout-long-finger/non_drawer_dialpad.xml b/phone/res/layout-long-finger/non_drawer_dialpad.xml
index 34a5b93..ac21ed0 100644
--- a/phone/res/layout-long-finger/non_drawer_dialpad.xml
+++ b/phone/res/layout-long-finger/non_drawer_dialpad.xml
@@ -22,7 +22,7 @@
      dtmf_twelve_key_dialer.xml and dialpad.xml, but in a more
      compact layout, and without the SlidingDrawer container.
      -->
-<com.android.phone2.DTMFTwelveKeyDialerView
+<com.android.phone.DTMFTwelveKeyDialerView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/non_drawer_dtmf_dialer"
     android:layout_width="match_parent"
@@ -54,7 +54,7 @@
         android:clickable="false"/>
 
     <!-- The dialpad itself -->
-    <com.android.phone2.ButtonGridLayout
+    <com.android.phone.ButtonGridLayout
         android:id="@+id/dialpad"
         android:paddingLeft="7dp"
         android:paddingRight="7dp"
@@ -147,6 +147,6 @@
                      android:src="@drawable/dial_num_pound"
                      android:background="@drawable/btn_dial_green"
                      />
-    </com.android.phone2.ButtonGridLayout>
+    </com.android.phone.ButtonGridLayout>
 
-</com.android.phone2.DTMFTwelveKeyDialerView>
+</com.android.phone.DTMFTwelveKeyDialerView>
diff --git a/phone/res/layout/call_card.xml b/phone/res/layout/call_card.xml
index f32edb5..663f114 100644
--- a/phone/res/layout/call_card.xml
+++ b/phone/res/layout/call_card.xml
@@ -63,6 +63,7 @@
             android:layout_height="101dp"
             android:layout_marginTop="-6dip"
             android:background="@drawable/incall_photo_border_med"
+            android:contentDescription="@string/onHold"
             />
     </LinearLayout>
 
diff --git a/phone/res/layout/call_card_person_info.xml b/phone/res/layout/call_card_person_info.xml
index e2c9489..b5a6901 100644
--- a/phone/res/layout/call_card_person_info.xml
+++ b/phone/res/layout/call_card_person_info.xml
@@ -41,6 +41,7 @@
                    android:layout_height="166dp"
                    android:layout_centerHorizontal="true"
                    android:background="@drawable/incall_photo_border_lg"
+                   android:contentDescription="@string/contactPhoto"
                    />
 
         <!-- The big "Manage conference" button that we show in place of
diff --git a/phone/res/layout/caller_in_conference.xml b/phone/res/layout/caller_in_conference.xml
index 630b44b..93406ec 100644
--- a/phone/res/layout/caller_in_conference.xml
+++ b/phone/res/layout/caller_in_conference.xml
@@ -36,7 +36,8 @@
             android:layout_height="46dp"
             android:layout_marginTop="2dp"
             android:layout_marginLeft="6dp"
-            android:scaleType="center"/>
+            android:scaleType="center"
+            android:contentDescription="@string/onscreenEndCallText" />
 
         <!-- Caller information -->
         <LinearLayout
@@ -97,7 +98,8 @@
             android:layout_height="46dp"
             android:layout_marginTop="2dp"
             android:layout_marginRight="6dp"
-            android:scaleType="center"/>
+            android:scaleType="center"
+            android:contentDescription="@string/goPrivate"/>
 
     </LinearLayout>  <!-- End of single list element -->
 
diff --git a/phone/res/layout/incall_screen.xml b/phone/res/layout/incall_screen.xml
index e291ac1..aa313e3 100644
--- a/phone/res/layout/incall_screen.xml
+++ b/phone/res/layout/incall_screen.xml
@@ -38,7 +38,7 @@
                         >
             <!-- The "Call Card", which displays info about the currently
                  active phone call(s) on the device.  See call_card.xml. -->
-            <com.android.phone2.CallCard android:id="@+id/callCard"
+            <com.android.phone.CallCard android:id="@+id/callCard"
                                         android:layout_width="match_parent"
                                         android:layout_height="match_parent"
                 />
@@ -68,9 +68,11 @@
          widget needs to be be a direct child of a FrameLayout anyway.)
          This is used only on devices that do *not* have an onscreen
          InCallTouchUi widget.-->
-    <!-- TODO: this should be a ViewStub, and should only get inflated
-         on platforms that need it. -->
-    <include layout="@layout/dtmf_twelve_key_dialer"/>
+    <ViewStub android:id="@+id/dtmf_dialer_stub"
+              android:layout="@layout/dtmf_twelve_key_dialer"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              />
 
     <!-- Finally, the "touch lock" overlay, drawn on top of the DTMF
          dialpad (after some delay) to prevent false touches from
@@ -103,34 +105,43 @@
     <!-- In-call onscreen touch controls, used on some platforms. -->
     <!-- TODO: if this widget ends up being totally unused on some platforms,
          then this should probably be a ViewStub. -->
-    <com.android.phone2.InCallTouchUi
+    <com.android.phone.InCallTouchUi
         android:id="@+id/inCallTouchUi"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         />
 
-    <!-- Frame where the provider's badge will be
+    <!-- Layout where the provider's badge will be
          inflated. The badge must fit in the available height.
          The badge is displayed for 5s on top of the contact's
          picture.
       -->
-    <FrameLayout android:id="@+id/inCallProviderOverlay"
+    <LinearLayout android:id="@+id/inCallProviderOverlay"
         android:background="@drawable/dialog_bg_calling_via"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:minHeight="88dip"
+        android:layout_height="88dip"
         android:layout_marginTop="8dip"
         android:layout_gravity="top"
-        android:visibility="gone">
+        android:gravity="center"
+        android:visibility="gone"
+        android:orientation="horizontal">
+
+         <ImageView android:id="@+id/callingViaIcon"
+            android:layout_width="40dip"
+            android:layout_height="40dip"
+            />
         <TextView android:id="@+id/callingVia"
             android:text="@string/calling_via_template"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
+            android:layout_weight="1"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:textAppearance="?android:attr/textAppearanceSmallInverse"
             android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMediumInverse"
-            android:textSize="16sp"
             />
-    </FrameLayout>
+        <View
+            android:layout_width="40dip"
+            android:layout_height="40dip"
+            />
+    </LinearLayout>
 
 </FrameLayout>
diff --git a/phone/res/layout/incall_touch_ui.xml b/phone/res/layout/incall_touch_ui.xml
index a85f8cc..0217d02 100644
--- a/phone/res/layout/incall_touch_ui.xml
+++ b/phone/res/layout/incall_touch_ui.xml
@@ -64,7 +64,8 @@
                 android:visibility="gone">
             <ImageButton android:id="@+id/holdButton"
                     style="@style/InCallRoundTouchButton"
-                    android:src="@drawable/ic_in_call_touch_round_hold" />
+                    android:src="@drawable/ic_in_call_touch_round_hold"
+                    android:contentDescription="@string/onscreenHoldText" />
             <TextView android:id="@+id/holdButtonLabel"
                     style="@style/InCallRoundButtonLabel" />
         </LinearLayout>
@@ -78,7 +79,8 @@
                 android:visibility="gone">
             <ImageButton android:id="@+id/swapButton"
                     style="@style/InCallRoundTouchButton"
-                    android:src="@drawable/ic_in_call_touch_round_swap" />
+                    android:src="@drawable/ic_in_call_touch_round_swap"
+                    android:contentDescription="@string/onscreenSwapCallsText"/>
             <TextView android:id="@+id/swapButtonLabel"
                 style="@style/InCallRoundButtonLabel" />
         </LinearLayout>
@@ -94,7 +96,8 @@
                 android:visibility="gone">
             <ImageButton android:id="@+id/cdmaMergeButton"
                     style="@style/InCallRoundTouchButton"
-                    android:src="@drawable/ic_in_call_touch_round_merge_call" />
+                    android:src="@drawable/ic_in_call_touch_round_merge_call"
+                    android:contentDescription="@string/onscreenMergeCallsText" />
             <TextView
                 style="@style/InCallRoundButtonLabel"
                 android:text="@string/onscreenMergeCallsText" />
@@ -102,9 +105,11 @@
 
         <!-- DTMF dialpad shown in the upper part of the screen
              (above the main cluster of buttons.) -->
-        <!-- TODO: this should be a ViewStub, and should only get inflated
-             when first needed. -->
-        <include layout="@layout/non_drawer_dialpad"/>
+        <ViewStub android:id="@+id/non_drawer_dialpad_stub"
+                  android:layout="@layout/non_drawer_dialpad"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent"
+                  />
 
         <!-- Main cluster of onscreen buttons on the lower part of the screen. -->
         <LinearLayout android:id="@+id/bottomButtons"
@@ -177,7 +182,7 @@
                         android:layout_height="wrap_content"
                         android:text="@string/onscreenEndCallText"
                         android:drawableTop="@drawable/ic_in_call_touch_end"
-                        android:textColor="@color/incall_endButtonLabel"
+                        android:textColor="@color/end_call_button_text"
                         />
 
                 <!-- "Dialpad" -->
diff --git a/phone/res/layout/ongoing_call_notification.xml b/phone/res/layout/ongoing_call_notification.xml
index a7302d3..e08d1cb 100644
--- a/phone/res/layout/ongoing_call_notification.xml
+++ b/phone/res/layout/ongoing_call_notification.xml
@@ -15,45 +15,53 @@
 -->
 
 <!-- Layout file for the custom "expanded view" used by the ongoing call
-     Notification; see NotificationMgr.updateInCallNotification(). -->
+     Notification; see NotificationMgr.updateInCallNotification().
+     This is largely copied from status_bar_latest_event_content,
+     but with some customizations -->
+
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
-    android:baselineAligned="false"
-    android:gravity="center_vertical"
-    android:layout_width="match_parent"
-    android:layout_height="65sp"
-    android:background="@android:drawable/status_bar_item_background"
-    >
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:paddingTop="7dp"
+        android:paddingLeft="5dp"
+        >
 
-   <ImageView android:id="@+id/icon"
-        android:layout_width="wrap_content"
+    <LinearLayout
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingLeft="4dip"
-        android:layout_marginRight="6dip" />
-
-   <LinearLayout
-       android:layout_width="wrap_content"
-       android:layout_height="wrap_content"
-       android:orientation="vertical"
-       >
-       <!-- The appearance of these 2 lines of text matches the other
-             kinds of notifications (see status_bar_latest_event.xml).
-             TODO: There should probably be common styles for these, though. -->
-       <Chronometer android:id="@+id/text1"
-           android:textStyle="bold"
-           android:textSize="18sp"
-           android:textColor="#ff000000"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:singleLine="true"
-           />
-       <TextView android:id="@+id/text2"
-           android:textSize="14sp"
-           android:textColor="#ff000000"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:singleLine="true"
-           />
-   </LinearLayout>
-       
+        android:orientation="horizontal"
+        android:paddingTop="3dp"
+        >
+        <ImageView android:id="@+id/icon"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:paddingLeft="4dip"
+             android:layout_marginRight="6dip" />
+        <Chronometer android:id="@+id/text1"
+            android:textStyle="bold"
+            android:textSize="18sp"
+            android:textColor="#ff000000"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            />
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        >
+        <TextView android:id="@+id/text2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:textColor="#ff000000"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal"
+            android:textSize="14sp"
+            android:paddingLeft="4dp"
+            />
+    </LinearLayout>
 </LinearLayout>
diff --git a/phone/res/layout/otacall_card.xml b/phone/res/layout/otacall_card.xml
index 246c042..23db2fc 100644
--- a/phone/res/layout/otacall_card.xml
+++ b/phone/res/layout/otacall_card.xml
@@ -76,7 +76,7 @@
                       />
 
             <!-- DTMF Dialer section -->
-            <com.android.phone2.DTMFTwelveKeyDialerView
+            <com.android.phone.DTMFTwelveKeyDialerView
                     xmlns:android="http://schemas.android.com/apk/res/android"
                     android:id="@+id/otaDtmfDialer"
                     android:layout_width="match_parent"
@@ -92,7 +92,7 @@
                 <!-- Keypad section -->
                 <include layout="@layout/dialpad" />
 
-            </com.android.phone2.DTMFTwelveKeyDialerView>
+            </com.android.phone.DTMFTwelveKeyDialerView>
 
         </LinearLayout>
 
@@ -136,6 +136,8 @@
         <!-- "End" button -->
         <Button android:id="@+id/otaEndButton"
                 android:text="@string/ota_call_end"
+                android:drawableLeft="@drawable/ic_btn_back"
+                android:drawablePadding="3dip"
                 style="@style/ccOtaSkipButton" />
     </RelativeLayout>
 
@@ -147,6 +149,8 @@
         <!-- "Next" button -->
         <Button android:id="@+id/otaNextButton"
                 android:text="@string/ota_next"
+                android:drawableRight="@drawable/ic_btn_next"
+                android:drawablePadding="10dip"
                 style="@style/ccOtaNextButton" />
 
         <!-- "Try Again" button -->
diff --git a/phone/res/layout/pref_dialog_editphonenumber.xml b/phone/res/layout/pref_dialog_editphonenumber.xml
index fc25d8c..8031c70 100644
--- a/phone/res/layout/pref_dialog_editphonenumber.xml
+++ b/phone/res/layout/pref_dialog_editphonenumber.xml
@@ -52,7 +52,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:padding="10dip"
-            android:src="@drawable/ic_button_contacts" />
+            android:src="@drawable/ic_button_contacts"
+            android:contentDescription="@string/selectContact" />
     </LinearLayout>
     
 </LinearLayout>
diff --git a/phone/res/values/config.xml b/phone/res/values/config.xml
index 5c84336..3e9dee0 100644
--- a/phone/res/values/config.xml
+++ b/phone/res/values/config.xml
@@ -119,4 +119,8 @@
     <!-- Determines if device implements a noise suppression device for in call audio-->
     <bool name="has_in_call_noise_suppression">false</bool>
 
+    <!-- Determines if the current device should allow emergency numbers
+         to be logged in the Call Log. -->
+    <bool name="allow_emergency_numbers_in_call_log">true</bool>
+
 </resources>
diff --git a/phone/res/values/strings.xml b/phone/res/values/strings.xml
index f6d4839..1ff406c 100755
--- a/phone/res/values/strings.xml
+++ b/phone/res/values/strings.xml
@@ -85,6 +85,8 @@
     <string name="callFailed_cdma_preempted">CDMA: Preempted.</string>
     <!-- In-call screen: call failure reason (Only Emergency calls are possible)-->
     <string name="callFailed_cdma_notEmergency">Only Emergency calls are possible.</string>
+    <!-- In-call screen: call failure reason (Dialed number doesn't exist) -->
+    <string name="callFailed_unobtainable_number">Invalid Number</string>
     <!-- In-call screen: status label for a conference call -->
     <string name="confCall">Conference call</string>
     <!-- In-call screen: call lost dialog text -->
@@ -323,6 +325,8 @@
     <string name="response_error">Unexpected response from network.</string>
     <!-- Status message displayed in the "Call settings error" dialog -->
     <string name="exception_error">Network or SIM card error.</string>
+    <!-- Status message displayed in the "Call settings error" dialog when operation fails due to FDN -->
+    <string name="fdn_only_error">Operations are only allowed on fixed dialing numbers.</string>
     <!-- Status message displayed in the "Call settings error" dialog -->
     <string name="radio_off_error">Please turn on the radio before viewing these settings.</string>
     <!-- Button label used to dismiss the "Call settings error" dialog -->
@@ -655,14 +659,14 @@
         <item>"1"</item>
         <item>"2"</item>
     </string-array>
-    <string name="subscription_title">CDMA Subscription TEST</string>
-    <string name="subscription_summary">Change between RUIM/SIM and NV</string>
-    <string name="subscription_dialogtitle">subscription</string>
-    <string-array name="subscription_choices">
+    <string name="cdma_subscription_title">CDMA Subscription</string>
+    <string name="cdma_subscription_summary">Change between RUIM/SIM and NV</string>
+    <string name="cdma_subscription_dialogtitle">subscription</string>
+    <string-array name="cdma_subscription_choices">
         <item>RUIM/SIM</item>
         <item>NV</item>
     </string-array>
-    <string-array name="subscription_values">
+    <string-array name="cdma_subscription_values">
         <item>"0"</item>
         <item>"1"</item>
     </string-array>
@@ -1189,4 +1193,10 @@
     <!-- Incoming call hint shown on tab (must be kept very short): decline incoming call -->
     <string name="slide_to_decline_hint">Decline</string>
 
+    <!-- Use this as a default to describe the contact photo; currently for screen readers through accessibility. -->
+    <string name="contactPhoto">contact photo</string>
+    <!-- Use this to describe the separate conference call button; currently for screen readers through accessibility. -->
+    <string name="goPrivate">go private</string>
+    <!--  Use this to describe the select contact button in EditPhoneNumberPreference; currently for screen readers through accessibility. -->
+    <string name="selectContact">select contact</string>
 </resources>
diff --git a/phone/res/values/styles.xml b/phone/res/values/styles.xml
index fdc1766..0850ade 100644
--- a/phone/res/values/styles.xml
+++ b/phone/res/values/styles.xml
@@ -176,7 +176,7 @@
         <item name="android:layout_marginLeft">8dip</item>
         <item name="android:layout_marginRight">8dip</item>
         <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
-        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textColor">@color/in_call_button_text</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">marquee</item>
     </style>
@@ -190,7 +190,7 @@
         <item name="android:layout_marginLeft">8dip</item>
         <item name="android:layout_marginRight">8dip</item>
         <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
-        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textColor">@color/in_call_button_text</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">marquee</item>
     </style>
diff --git a/phone/res/xml/cdma_options.xml b/phone/res/xml/cdma_options.xml
index e2ff8df..3ca8c2f 100644
--- a/phone/res/xml/cdma_options.xml
+++ b/phone/res/xml/cdma_options.xml
@@ -17,11 +17,20 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:settings="http://schemas.android.com/apk/res/com.android.phone2">
 
-    <com.android.phone2.CdmaRoamingListPreference
-        android:key="cdma_roaming_mode_key"
+    <com.android.phone2.CdmaSystemSelectListPreference
+        android:key="cdma_system_select_key"
         android:title="@string/cdma_system_select_title"
         android:summary="@string/cdma_system_select_summary"
         android:entries="@array/cdma_system_select_choices"
         android:entryValues="@array/cdma_system_select_values"
         android:dialogTitle="@string/cdma_system_select_dialogtitle" />
+
+    <com.android.phone2.CdmaSubscriptionListPreference
+        android:key="cdma_subscription_key"
+        android:title="@string/cdma_subscription_title"
+        android:summary="@string/cdma_subscription_summary"
+        android:entries="@array/cdma_subscription_choices"
+        android:entryValues="@array/cdma_subscription_values"
+        android:dialogTitle="@string/cdma_subscription_dialogtitle" />
+
 </PreferenceScreen>
diff --git a/phone/res/xml/network_setting.xml b/phone/res/xml/network_setting.xml
index 0c579a3..43b688a 100644
--- a/phone/res/xml/network_setting.xml
+++ b/phone/res/xml/network_setting.xml
@@ -48,26 +48,4 @@
         android:entryValues="@array/preferred_network_mode_values"
         android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
 
-    <PreferenceScreen
-        android:key="gsm_umts_options_key"
-        android:title="@string/gsm_umts_options"
-        android:persistent="false">
-
-        <intent android:action="android.intent.action.MAIN"
-            android:targetPackage="com.android.phone2"
-            android:targetClass="com.android.phone2.GsmUmtsOptions" />
-
-    </PreferenceScreen>
-
-    <PreferenceScreen
-        android:key="cdma_options_key"
-        android:title="@string/cdma_options"
-        android:persistent="false">
-
-        <intent android:action="android.intent.action.MAIN"
-            android:targetPackage="com.android.phone2"
-            android:targetClass="com.android.phone2.CdmaOptions" />
-
-    </PreferenceScreen>
-
 </PreferenceScreen>
diff --git a/phone/src/com/android/phone2/BluetoothHandsfree.java b/phone/src/com/android/phone2/BluetoothHandsfree.java
index 63ad4f3..29a6c8b 100644
--- a/phone/src/com/android/phone2/BluetoothHandsfree.java
+++ b/phone/src/com/android/phone2/BluetoothHandsfree.java
@@ -241,7 +241,7 @@
         return mHeadset.isConnected();
     }
 
-    /* package */ void connectHeadset(HeadsetBase headset, int headsetType) {
+    /* package */ synchronized void connectHeadset(HeadsetBase headset, int headsetType) {
         mHeadset = headset;
         mHeadsetType = headsetType;
         if (mHeadsetType == TYPE_HEADSET) {
@@ -277,7 +277,7 @@
         resetAtState();
     }
 
-    private void resetAtState() {
+    /* package */ synchronized void resetAtState() {
         mClip = false;
         mIndicatorsEnabled = false;
         mServiceConnectionEstablished = false;
diff --git a/phone/src/com/android/phone2/BluetoothHeadsetService.java b/phone/src/com/android/phone2/BluetoothHeadsetService.java
index 1d78cdb..f36309e 100644
--- a/phone/src/com/android/phone2/BluetoothHeadsetService.java
+++ b/phone/src/com/android/phone2/BluetoothHeadsetService.java
@@ -437,6 +437,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
             case HeadsetBase.RFCOMM_DISCONNECTED:
+                mBtHandsfree.resetAtState();
                 setState(BluetoothHeadset.STATE_DISCONNECTED, BluetoothHeadset.RESULT_FAILURE,
                          BluetoothHeadset.REMOTE_DISCONNECT);
                 break;
@@ -490,7 +491,8 @@
         }
     }
 
-    private void getSdpRecordsAndConnect() {
+    private synchronized void getSdpRecordsAndConnect() {
+        if (mRemoteDevice == null) return;
         ParcelUuid[] uuids = mRemoteDevice.getUuids();
         if (uuids != null) {
             if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
diff --git a/phone/src/com/android/phone2/CLIRListPreference.java b/phone/src/com/android/phone2/CLIRListPreference.java
index 0e81513..1b6dca7 100644
--- a/phone/src/com/android/phone2/CLIRListPreference.java
+++ b/phone/src/com/android/phone2/CLIRListPreference.java
@@ -1,11 +1,9 @@
 package com.android.phone2;
 
-import static com.android.phone2.TimeConsumingPreferenceActivity.EXCEPTION_ERROR;
 import static com.android.phone2.TimeConsumingPreferenceActivity.RESPONSE_ERROR;
-
+import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 import android.content.Context;
 import android.os.AsyncResult;
@@ -29,7 +27,7 @@
     public CLIRListPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        phone = PhoneFactory.getDefaultPhone();
+        phone = PhoneApp.getPhone();
     }
 
     public CLIRListPreference(Context context) {
@@ -133,8 +131,7 @@
             clirArray = null;
             if (ar.exception != null) {
                 if (DBG) Log.d(LOG_TAG, "handleGetCLIRResponse: ar.exception="+ar.exception);
-                setEnabled(false);
-                tcpListener.onError(CLIRListPreference.this, EXCEPTION_ERROR);
+                tcpListener.onException(CLIRListPreference.this, (CommandException) ar.exception);
             } else if (ar.userObj instanceof Throwable) {
                 tcpListener.onError(CLIRListPreference.this, RESPONSE_ERROR);
             } else {
diff --git a/phone/src/com/android/phone2/CallCard.java b/phone/src/com/android/phone2/CallCard.java
index 47d640c..5c39c5d 100755
--- a/phone/src/com/android/phone2/CallCard.java
+++ b/phone/src/com/android/phone2/CallCard.java
@@ -984,6 +984,10 @@
                     resID = R.string.callFailed_outOfService;
                     break;
 
+                case UNOBTAINABLE_NUMBER:
+                    resID = R.string.callFailed_unobtainable_number;
+                    break;
+
                 default:
                     resID = R.string.card_title_call_ended;
                     break;
diff --git a/phone/src/com/android/phone2/CallFeaturesSetting.java b/phone/src/com/android/phone2/CallFeaturesSetting.java
index f0f8e31..9f9f2d8 100644
--- a/phone/src/com/android/phone2/CallFeaturesSetting.java
+++ b/phone/src/com/android/phone2/CallFeaturesSetting.java
@@ -49,7 +49,6 @@
 import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.cdma.TtyIntent;
 
 import java.util.Collection;
@@ -1304,7 +1303,7 @@
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         if (DBG) log("Creating activity");
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
 
         addPreferencesFromResource(R.xml.call_feature_setting);
 
diff --git a/phone/src/com/android/phone2/CallForwardEditPreference.java b/phone/src/com/android/phone2/CallForwardEditPreference.java
index a30b3f9..41688bf 100644
--- a/phone/src/com/android/phone2/CallForwardEditPreference.java
+++ b/phone/src/com/android/phone2/CallForwardEditPreference.java
@@ -1,9 +1,9 @@
 package com.android.phone2;
 
 import com.android.internal.telephony.CallForwardInfo;
+import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 import android.app.AlertDialog;
 import android.content.Context;
@@ -16,7 +16,6 @@
 import android.util.AttributeSet;
 import android.util.Log;
 
-import static com.android.phone2.TimeConsumingPreferenceActivity.EXCEPTION_ERROR;
 import static com.android.phone2.TimeConsumingPreferenceActivity.RESPONSE_ERROR;
 
 public class CallForwardEditPreference extends EditPhoneNumberPreference {
@@ -36,7 +35,7 @@
     public CallForwardEditPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        phone = PhoneFactory.getDefaultPhone();
+        phone = PhoneApp.getPhone();
         mSummaryOnTemplate = this.getSummaryOn();
 
         TypedArray a = context.obtainStyledAttributes(attrs,
@@ -178,8 +177,8 @@
             callForwardInfo = null;
             if (ar.exception != null) {
                 if (DBG) Log.d(LOG_TAG, "handleGetCFResponse: ar.exception=" + ar.exception);
-                setEnabled(false);
-                tcpListener.onError(CallForwardEditPreference.this, EXCEPTION_ERROR);
+                tcpListener.onException(CallForwardEditPreference.this,
+                        (CommandException) ar.exception);
             } else {
                 if (ar.userObj instanceof Throwable) {
                     tcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
diff --git a/phone/src/com/android/phone2/CallNotifier.java b/phone/src/com/android/phone2/CallNotifier.java
index 9df72ab..5d20895 100755
--- a/phone/src/com/android/phone2/CallNotifier.java
+++ b/phone/src/com/android/phone2/CallNotifier.java
@@ -155,7 +155,7 @@
     private static final int TONE_RELATIVE_VOLUME_SIGNALINFO = 80;
 
     private Call.State mPreviousCdmaCallState;
-    private boolean mCdmaVoicePrivacyState = false;
+    private boolean mVoicePrivacyState = false;
     private boolean mIsCdmaRedialCall = false;
 
     // Emergency call tone and vibrate:
@@ -180,39 +180,19 @@
 
         mAudioManager = (AudioManager) mPhone.getContext().getSystemService(Context.AUDIO_SERVICE);
 
-        mPhone.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
-        mPhone.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null);
-        mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);
-        mPhone.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
-        mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
+        registerForNotifications();
 
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            mPhone.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);
-
-            if (DBG) log("Registering for Call Waiting, Signal and Display Info.");
-            mPhone.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
-            mPhone.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
-            mPhone.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
-            mPhone.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);
-            mPhone.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);
-
-            // Instantiate the ToneGenerator for SignalInfo and CallWaiting
-            // TODO: We probably don't need the mSignalInfoToneGenerator instance
-            // around forever. Need to change it so as to create a ToneGenerator instance only
-            // when a tone is being played and releases it after its done playing.
-            try {
-                mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL,
-                        TONE_RELATIVE_VOLUME_SIGNALINFO);
-            } catch (RuntimeException e) {
-                Log.w(LOG_TAG, "CallNotifier: Exception caught while creating " +
-                        "mSignalInfoToneGenerator: " + e);
-                mSignalInfoToneGenerator = null;
-            }
-        }
-
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_GSM) {
-            mPhone.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);
-            mPhone.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);
+        // Instantiate the ToneGenerator for SignalInfo and CallWaiting
+        // TODO: We probably don't need the mSignalInfoToneGenerator instance
+        // around forever. Need to change it so as to create a ToneGenerator instance only
+        // when a tone is being played and releases it after its done playing.
+        try {
+            mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL,
+                    TONE_RELATIVE_VOLUME_SIGNALINFO);
+        } catch (RuntimeException e) {
+            Log.w(LOG_TAG, "CallNotifier: Exception caught while creating " +
+                    "mSignalInfoToneGenerator: " + e);
+            mSignalInfoToneGenerator = null;
         }
 
         mRinger = ringer;
@@ -328,10 +308,10 @@
 
             case PHONE_ENHANCED_VP_ON:
                 if (DBG) log("PHONE_ENHANCED_VP_ON...");
-                if (!mCdmaVoicePrivacyState) {
+                if (!mVoicePrivacyState) {
                     int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY;
                     new InCallTonePlayer(toneToPlay).start();
-                    mCdmaVoicePrivacyState = true;
+                    mVoicePrivacyState = true;
                     // Update the VP icon:
                     NotificationMgr.getDefault().updateInCallNotification();
                 }
@@ -339,10 +319,10 @@
 
             case PHONE_ENHANCED_VP_OFF:
                 if (DBG) log("PHONE_ENHANCED_VP_OFF...");
-                if (mCdmaVoicePrivacyState) {
+                if (mVoicePrivacyState) {
                     int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY;
                     new InCallTonePlayer(toneToPlay).start();
-                    mCdmaVoicePrivacyState = false;
+                    mVoicePrivacyState = false;
                     // Update the VP icon:
                     NotificationMgr.getDefault().updateInCallNotification();
                 }
@@ -389,7 +369,7 @@
         }
 
         // Incoming calls are totally ignored if OTA call is active
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+        if (TelephonyCapabilities.supportsOtasp(mPhone)) {
             boolean activateState = (mApplication.cdmaOtaScreenState.otaScreenState
                     == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION);
             boolean dialogState = (mApplication.cdmaOtaScreenState.otaScreenState
@@ -409,9 +389,7 @@
 
         if (c != null && c.isRinging()) {
             // Stop any signalInfo tone being played on receiving a Call
-            if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-                stopSignalInfoTone();
-            }
+            stopSignalInfoTone();
 
             Call.State state = c.getState();
             // State will be either INCOMING or WAITING.
@@ -741,36 +719,26 @@
         mPhone.unregisterForInCallVoicePrivacyOff(this);
 
         // Register all events new to the new active phone
+        registerForNotifications();
+    }
+
+    private void registerForNotifications() {
         mPhone.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
         mPhone.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null);
         mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);
         mPhone.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
         mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            if (DBG) log("Registering for Call Waiting, Signal and Display Info.");
-            mPhone.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
-            mPhone.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
-            mPhone.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
+
+        if (TelephonyCapabilities.supportsOtasp(mPhone)) {
             mPhone.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);
-
-            // Instantiate the ToneGenerator for SignalInfo
-            try {
-                mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL,
-                        TONE_RELATIVE_VOLUME_SIGNALINFO);
-            } catch (RuntimeException e) {
-                Log.w(LOG_TAG, "CallNotifier: Exception caught while creating " +
-                        "mSignalInfoToneGenerator: " + e);
-                mSignalInfoToneGenerator = null;
-            }
-
-            mPhone.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);
-            mPhone.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);
         }
-
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_GSM) {
-            mPhone.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);
-            mPhone.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);
-        }
+        mPhone.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
+        mPhone.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
+        mPhone.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
+        mPhone.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);
+        mPhone.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);
+        mPhone.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);
+        mPhone.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);
     }
 
     /**
@@ -823,7 +791,7 @@
     private void onDisconnect(AsyncResult r) {
         if (VDBG) log("onDisconnect()...  phone state: " + mPhone.getState());
 
-        mCdmaVoicePrivacyState = false;
+        mVoicePrivacyState = false;
         int autoretrySetting = 0;
         if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
             autoretrySetting = android.provider.Settings.System.getInt(mPhone.getContext().
@@ -834,10 +802,10 @@
             PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_IDLE);
         }
 
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            // Stop any signalInfo tone being played when a call gets ended
-            stopSignalInfoTone();
+        // Stop any signalInfo tone being played when a call gets ended
+        stopSignalInfoTone();
 
+        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
             // Resetting the CdmaPhoneCallState members
             mApplication.cdmaPhoneCallState.resetCdmaPhoneCallState();
 
@@ -917,6 +885,9 @@
             } else if (cause == Connection.DisconnectCause.OUT_OF_SERVICE) {
                 if (DBG) log("- need to play OUT OF SERVICE tone!");
                 toneToPlay = InCallTonePlayer.TONE_OUT_OF_SERVICE;
+            } else if (cause == Connection.DisconnectCause.UNOBTAINABLE_NUMBER) {
+                if (DBG) log("- need to play TONE_UNOBTAINABLE_NUMBER tone!");
+                toneToPlay = InCallTonePlayer.TONE_UNOBTAINABLE_NUMBER;
             } else if (cause == Connection.DisconnectCause.ERROR_UNSPECIFIED) {
                 if (DBG) log("- DisconnectCause is ERROR_UNSPECIFIED: play TONE_CALL_ENDED!");
                 toneToPlay = InCallTonePlayer.TONE_CALL_ENDED;
@@ -1001,26 +972,30 @@
                     }
                 }
 
-                // To prevent accidental redial of emergency numbers
-                // (carrier requirement) the quickest solution is to
-                // not log the emergency number. We gate on CDMA
-                // (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);
+                // On some devices, to avoid accidental redialing of
+                // emergency numbers, we *never* log emergency calls to
+                // the Call Log.  (This behavior is set on a per-product
+                // basis, based on carrier requirements.)
+                final boolean okToLogEmergencyNumber =
+                        mApplication.getResources().getBoolean(
+                                R.bool.allow_emergency_numbers_in_call_log);
 
-                // Don't call isOtaSpNumber on GSM phones.
-                final boolean isOtaNumber = (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA)
+                // Don't call isOtaSpNumber() on phones that don't support OTASP.
+                final boolean isOtaspNumber = TelephonyCapabilities.supportsOtasp(mPhone)
                         && mPhone.isOtaSpNumber(number);
                 final boolean isEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(number);
 
-                // Don't put OTA or CDMA Emergency calls into call log
-                if (!(isOtaNumber || isEmergencyNumber && shouldNotlogEmergencyNumber)) {
+                // Don't log emergency numbers if the device doesn't allow it,
+                // and never log OTASP calls.
+                final boolean okToLogThisCall =
+                        (!isEmergencyNumber || okToLogEmergencyNumber)
+                        && !isOtaspNumber;
+
+                if (okToLogThisCall) {
                     CallLogAsync.AddCallArgs args =
                             new CallLogAsync.AddCallArgs(
                                 mPhone.getContext(), ci, logNumber, presentation,
                                 callLogType, date, duration);
-
                     mCallLog.addCall(args);
                 }
             }
@@ -1077,7 +1052,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(mPhone.getContext(), mPhone, number, null, false, null);
                         mIsCdmaRedialCall = true;
                     } else {
                         mIsCdmaRedialCall = false;
@@ -1194,6 +1169,7 @@
         public static final int TONE_REDIAL = 11;
         public static final int TONE_OTA_CALL_END = 12;
         public static final int TONE_RING_BACK = 13;
+        public static final int TONE_UNOBTAINABLE_NUMBER = 14;
 
         // The tone volume relative to other sounds in the stream
         private static final int TONE_RELATIVE_VOLUME_HIPRI = 80;
@@ -1307,6 +1283,11 @@
                     // Call ring back tone is stopped by stopTone() method
                     toneLengthMillis = Integer.MAX_VALUE - TONE_TIMEOUT_BUFFER;
                     break;
+                case TONE_UNOBTAINABLE_NUMBER:
+                    toneType = ToneGenerator.TONE_SUP_ERROR;
+                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
+                    toneLengthMillis = 4000;
+                    break;
                 default:
                     throw new IllegalArgumentException("Bad toneId: " + mToneId);
             }
@@ -1653,10 +1634,10 @@
     }
 
     /**
-     * Return the private variable mCdmaVoicePrivacyState.
+     * Return the private variable mVoicePrivacyState.
      */
-    /* package */ boolean getCdmaVoicePrivacyState() {
-        return mCdmaVoicePrivacyState;
+    /* package */ boolean getVoicePrivacyState() {
+        return mVoicePrivacyState;
     }
 
     /**
diff --git a/phone/src/com/android/phone2/CallTime.java b/phone/src/com/android/phone2/CallTime.java
index a4c56eb..7798332 100644
--- a/phone/src/com/android/phone2/CallTime.java
+++ b/phone/src/com/android/phone2/CallTime.java
@@ -194,7 +194,7 @@
         if (PROFILE & sProfileState == PROFILE_STATE_READY) {
             // For now, we move away from temp directory in favor of
             // the application's data directory to store the trace
-            // information (/data/data/com.android.phone).
+            // information (/data/data/com.android.phone2).
             File file = PhoneApp.getInstance().getDir ("phoneTrace", Context.MODE_PRIVATE);
             if (file.exists() == false) {
                 file.mkdirs();
diff --git a/phone/src/com/android/phone2/CallWaitingCheckBoxPreference.java b/phone/src/com/android/phone2/CallWaitingCheckBoxPreference.java
index 1d59e8c..f03d01e 100644
--- a/phone/src/com/android/phone2/CallWaitingCheckBoxPreference.java
+++ b/phone/src/com/android/phone2/CallWaitingCheckBoxPreference.java
@@ -1,7 +1,10 @@
 package com.android.phone2;
 
-import static com.android.phone2.TimeConsumingPreferenceActivity.EXCEPTION_ERROR;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.Phone;
+
 import static com.android.phone2.TimeConsumingPreferenceActivity.RESPONSE_ERROR;
+
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
@@ -11,7 +14,6 @@
 import android.util.Log;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 public class CallWaitingCheckBoxPreference extends CheckBoxPreference {
     private static final String LOG_TAG = "CallWaitingCheckBoxPreference";
@@ -24,7 +26,7 @@
     public CallWaitingCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        phone = PhoneFactory.getDefaultPhone();
+        phone = PhoneApp.getPhone();
     }
 
     public CallWaitingCheckBoxPreference(Context context, AttributeSet attrs) {
@@ -86,9 +88,13 @@
             }
 
             if (ar.exception != null) {
-                if (DBG) Log.d(LOG_TAG, "handleGetCallWaitingResponse: ar.exception=" + ar.exception);
-                setEnabled(false);
-                if (tcpListener != null) tcpListener.onError(CallWaitingCheckBoxPreference.this, EXCEPTION_ERROR);
+                if (DBG) {
+                    Log.d(LOG_TAG, "handleGetCallWaitingResponse: ar.exception=" + ar.exception);
+                }
+                if (tcpListener != null) {
+                    tcpListener.onException(CallWaitingCheckBoxPreference.this,
+                            (CommandException)ar.exception);
+                }
             } else if (ar.userObj instanceof Throwable) {
                 if (tcpListener != null) tcpListener.onError(CallWaitingCheckBoxPreference.this, RESPONSE_ERROR);
             } else {
diff --git a/phone/src/com/android/phone2/CdmaCallOptions.java b/phone/src/com/android/phone2/CdmaCallOptions.java
index 3022962..3cdf86b 100644
--- a/phone/src/com/android/phone2/CdmaCallOptions.java
+++ b/phone/src/com/android/phone2/CdmaCallOptions.java
@@ -1,7 +1,6 @@
 package com.android.phone2;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 import android.content.DialogInterface;
 import android.os.AsyncResult;
@@ -28,7 +27,7 @@
         addPreferencesFromResource(R.xml.cdma_call_options);
 
         mButtonVoicePrivacy = (CheckBoxPreference) findPreference(BUTTON_VP_KEY);
-        if (PhoneFactory.getDefaultPhone().getPhoneType() != Phone.PHONE_TYPE_CDMA) {
+        if (PhoneApp.getPhone().getPhoneType() != Phone.PHONE_TYPE_CDMA) {
             //disable the entire screen
             getPreferenceScreen().setEnabled(false);
         }
diff --git a/phone/src/com/android/phone2/CdmaOptions.java b/phone/src/com/android/phone2/CdmaOptions.java
index 1081668..ec09133 100644
--- a/phone/src/com/android/phone2/CdmaOptions.java
+++ b/phone/src/com/android/phone2/CdmaOptions.java
@@ -16,42 +16,100 @@
 
 package com.android.phone2;
 
-import android.os.Bundle;
+import android.os.SystemProperties;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceScreen;
-
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
+import android.text.TextUtils;
 
 /**
  * List of Phone-specific settings screens.
  */
-public class CdmaOptions extends PreferenceActivity {
+public class CdmaOptions {
+    private static final String LOG_TAG = "CdmaOptions";
 
-    private CdmaRoamingListPreference mButtonCdmaRoam;
+    private CdmaSystemSelectListPreference mButtonCdmaSystemSelect;
+    private CdmaSubscriptionListPreference mButtonCdmaSubscription;
 
-    private static final String BUTTON_CDMA_ROAMING_KEY = "cdma_roaming_mode_key";
+    private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
+    private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
 
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
+    private PreferenceActivity mPrefActivity;
+    private PreferenceScreen mPrefScreen;
 
-        addPreferencesFromResource(R.xml.cdma_options);
+    public CdmaOptions(PreferenceActivity prefActivity, PreferenceScreen prefScreen) {
+        mPrefActivity = prefActivity;
+        mPrefScreen = prefScreen;
+        create();
+    }
 
-        PreferenceScreen prefSet = getPreferenceScreen();
-        mButtonCdmaRoam =
-                (CdmaRoamingListPreference) prefSet.findPreference(BUTTON_CDMA_ROAMING_KEY);
-        if (PhoneFactory.getDefaultPhone().getPhoneType() != Phone.PHONE_TYPE_CDMA) {
-            mButtonCdmaRoam.setEnabled(false);
+    protected void create() {
+        mPrefActivity.addPreferencesFromResource(R.xml.cdma_options);
+
+        mButtonCdmaSystemSelect = (CdmaSystemSelectListPreference)mPrefScreen
+                .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY);
+
+        mButtonCdmaSubscription = (CdmaSubscriptionListPreference)mPrefScreen
+                .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY);
+
+        mButtonCdmaSystemSelect.setEnabled(true);
+        if(deviceSupportsNvAndRuim()) {
+            log("Both NV and Ruim supported, ENABLE subscription type selection");
+            mButtonCdmaSubscription.setEnabled(true);
+        } else {
+            log("Both NV and Ruim NOT supported, REMOVE subscription type selection");
+            mPrefScreen.removePreference(mPrefScreen
+                                .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY));
         }
     }
 
-    @Override
-    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
-        if (preference.getKey().equals(BUTTON_CDMA_ROAMING_KEY)) {
+    private boolean deviceSupportsNvAndRuim() {
+        // retrieve the list of subscription types supported by device.
+        String subscriptionsSupported = SystemProperties.get("ril.subscription.types");
+        boolean nvSupported = false;
+        boolean ruimSupported = false;
+
+        log("deviceSupportsnvAnRum: prop=" + subscriptionsSupported);
+        if (!TextUtils.isEmpty(subscriptionsSupported)) {
+            // Searches through the comma-separated list for a match for "NV"
+            // and "RUIM" to update nvSupported and ruimSupported.
+            for (String subscriptionType : subscriptionsSupported.split(",")) {
+                subscriptionType = subscriptionType.trim();
+                if (subscriptionType.equalsIgnoreCase("NV")) {
+                    nvSupported = true;
+                }
+                if (subscriptionType.equalsIgnoreCase("RUIM")) {
+                    ruimSupported = true;
+                }
+            }
+        }
+
+        log("deviceSupportsnvAnRum: nvSupported=" + nvSupported +
+                " ruimSupported=" + ruimSupported);
+        return (nvSupported && ruimSupported);
+    }
+
+    public boolean preferenceTreeClick(Preference preference) {
+        if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
+            log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true");
+            return true;
+        }
+        if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+            log("preferenceTreeClick: return CDMA_SUBSCRIPTION_KEY true");
             return true;
         }
         return false;
     }
+
+    public void showDialog(Preference preference) {
+        if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
+            mButtonCdmaSystemSelect.showDialog(null);
+        } else if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
+            mButtonCdmaSubscription.showDialog(null);
+        }
+    }
+
+    protected void log(String s) {
+        android.util.Log.d(LOG_TAG, s);
+    }
 }
diff --git a/phone/src/com/android/phone2/CdmaSubscriptionListPreference.java b/phone/src/com/android/phone2/CdmaSubscriptionListPreference.java
new file mode 100644
index 0000000..c2ba664
--- /dev/null
+++ b/phone/src/com/android/phone2/CdmaSubscriptionListPreference.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone2;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.ListPreference;
+import android.provider.Settings.Secure;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
+public class CdmaSubscriptionListPreference extends ListPreference {
+
+    private static final String LOG_TAG = "CdmaSubscriptionListPreference";
+
+    // Used for CDMA subscription mode
+    private static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0;
+    private static final int CDMA_SUBSCRIPTION_NV = 1;
+
+    //preferredSubscriptionMode  0 - RUIM/SIM, preferred
+    //                           1 - NV
+    static final int preferredSubscriptionMode = CDMA_SUBSCRIPTION_NV;
+
+    private Phone mPhone;
+    private CdmaSubscriptionButtonHandler mHandler;
+
+    public CdmaSubscriptionListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mPhone = PhoneFactory.getDefaultPhone();
+        mHandler = new CdmaSubscriptionButtonHandler();
+        setCurrentCdmaSubscriptionModeValue();
+    }
+
+    private void setCurrentCdmaSubscriptionModeValue() {
+        int cdmaSubscriptionMode = Secure.getInt(mPhone.getContext().getContentResolver(),
+                android.provider.Settings.Secure.CDMA_SUBSCRIPTION_MODE, preferredSubscriptionMode);
+        setValue(Integer.toString(cdmaSubscriptionMode));
+    }
+
+    public CdmaSubscriptionListPreference(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    protected void showDialog(Bundle state) {
+        setCurrentCdmaSubscriptionModeValue();
+
+        super.showDialog(state);
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+
+        if (!positiveResult) {
+            //The button was dismissed - no need to set new value
+            return;
+        }
+
+        int buttonCdmaSubscriptionMode = Integer.valueOf(getValue()).intValue();
+        Log.d(LOG_TAG, "Setting new value " + buttonCdmaSubscriptionMode);
+        int statusCdmaSubscriptionMode;
+        switch(buttonCdmaSubscriptionMode) {
+            case CDMA_SUBSCRIPTION_NV:
+                statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_NV;
+                break;
+            case CDMA_SUBSCRIPTION_RUIM_SIM:
+                statusCdmaSubscriptionMode = Phone.CDMA_SUBSCRIPTION_RUIM_SIM;
+                break;
+            default:
+                statusCdmaSubscriptionMode = Phone.PREFERRED_CDMA_SUBSCRIPTION;
+        }
+
+        // Set the CDMA subscription mode, when mode has been successfully changed
+        // handleSetCdmaSubscriptionMode will be invoked and the value saved.
+        mPhone.setCdmaSubscription(statusCdmaSubscriptionMode, mHandler
+                .obtainMessage(CdmaSubscriptionButtonHandler.MESSAGE_SET_CDMA_SUBSCRIPTION,
+                        getValue()));
+
+    }
+
+    private class CdmaSubscriptionButtonHandler extends Handler {
+
+        private static final int MESSAGE_SET_CDMA_SUBSCRIPTION = 0;
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_SET_CDMA_SUBSCRIPTION:
+                    handleSetCdmaSubscriptionMode(msg);
+                    break;
+            }
+        }
+
+        private void handleSetCdmaSubscriptionMode(Message msg) {
+            mPhone = PhoneFactory.getDefaultPhone();
+            AsyncResult ar = (AsyncResult) msg.obj;
+
+            if (ar.exception == null) {
+                // Get the original string entered by the user
+                int cdmaSubscriptionMode = Integer.valueOf((String) ar.userObj).intValue();
+                Secure.putInt(mPhone.getContext().getContentResolver(),
+                        Secure.CDMA_SUBSCRIPTION_MODE,
+                        cdmaSubscriptionMode );
+            } else {
+                Log.e(LOG_TAG, "Setting Cdma subscription source failed");
+            }
+        }
+    }
+}
diff --git a/phone/src/com/android/phone2/CdmaRoamingListPreference.java b/phone/src/com/android/phone2/CdmaSystemSelectListPreference.java
similarity index 95%
rename from phone/src/com/android/phone2/CdmaRoamingListPreference.java
rename to phone/src/com/android/phone2/CdmaSystemSelectListPreference.java
index ac247cd..055981c 100644
--- a/phone/src/com/android/phone2/CdmaRoamingListPreference.java
+++ b/phone/src/com/android/phone2/CdmaSystemSelectListPreference.java
@@ -28,10 +28,9 @@
 import android.util.Log;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyProperties;
 
-public class CdmaRoamingListPreference extends ListPreference {
+public class CdmaSystemSelectListPreference extends ListPreference {
 
     private static final String LOG_TAG = "CdmaRoamingListPreference";
     private static final boolean DBG = true;
@@ -39,16 +38,16 @@
     private Phone mPhone;
     private MyHandler mHandler = new MyHandler();;
 
-    public CdmaRoamingListPreference(Context context, AttributeSet attrs) {
+    public CdmaSystemSelectListPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         mHandler = new MyHandler();
         mPhone.queryCdmaRoamingPreference(
                 mHandler.obtainMessage(MyHandler.MESSAGE_GET_ROAMING_PREFERENCE));
     }
 
-    public CdmaRoamingListPreference(Context context) {
+    public CdmaSystemSelectListPreference(Context context) {
         this(context, null);
     }
 
diff --git a/phone/src/com/android/phone2/CdmaVoicePrivacyCheckBoxPreference.java b/phone/src/com/android/phone2/CdmaVoicePrivacyCheckBoxPreference.java
index 6408365..9714970 100644
--- a/phone/src/com/android/phone2/CdmaVoicePrivacyCheckBoxPreference.java
+++ b/phone/src/com/android/phone2/CdmaVoicePrivacyCheckBoxPreference.java
@@ -1,7 +1,7 @@
 package com.android.phone2;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
+
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
@@ -20,7 +20,7 @@
     public CdmaVoicePrivacyCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        phone = PhoneFactory.getDefaultPhone();
+        phone = PhoneApp.getPhone();
         phone.getEnhancedVoicePrivacy(mHandler.obtainMessage(MyHandler.MESSAGE_GET_VP));
     }
 
diff --git a/phone/src/com/android/phone2/CellBroadcastSms.java b/phone/src/com/android/phone2/CellBroadcastSms.java
index ed34700..7114c78 100644
--- a/phone/src/com/android/phone2/CellBroadcastSms.java
+++ b/phone/src/com/android/phone2/CellBroadcastSms.java
@@ -24,7 +24,6 @@
 import android.preference.PreferenceScreen;
 import android.preference.PreferenceActivity;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.RILConstants;
 
 import android.os.AsyncResult;
@@ -338,7 +337,7 @@
 
         addPreferencesFromResource(R.xml.cell_broadcast_sms);
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         mHandler = new MyHandler();
 
         PreferenceScreen prefSet = getPreferenceScreen();
diff --git a/phone/src/com/android/phone2/ChangeIccPinScreen.java b/phone/src/com/android/phone2/ChangeIccPinScreen.java
index 34078e0..e890321 100644
--- a/phone/src/com/android/phone2/ChangeIccPinScreen.java
+++ b/phone/src/com/android/phone2/ChangeIccPinScreen.java
@@ -37,7 +37,6 @@
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 /**
  * "Change ICC PIN" UI for the Phone app.
@@ -92,7 +91,7 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
 
         resolveIntent();
 
diff --git a/phone/src/com/android/phone2/DTMFTwelveKeyDialer.java b/phone/src/com/android/phone2/DTMFTwelveKeyDialer.java
index da2313b..0947316 100755
--- a/phone/src/com/android/phone2/DTMFTwelveKeyDialer.java
+++ b/phone/src/com/android/phone2/DTMFTwelveKeyDialer.java
@@ -20,7 +20,6 @@
 import android.media.ToneGenerator;
 import android.os.Handler;
 import android.os.Message;
-import android.os.SystemProperties;
 import android.provider.Settings;
 import android.telephony.PhoneNumberUtils;
 import android.text.Editable;
@@ -62,11 +61,11 @@
     private ToneGenerator mToneGenerator;
     private Object mToneGeneratorLock = new Object();
 
-    // indicate if we want to enable the DTMF tone playback.
-    private boolean mDTMFToneEnabled;
+    // indicate if we want to enable the local tone playback.
+    private boolean mLocalToneEnabled;
 
-    // DTMF tone type
-    private int mDTMFToneType;
+    // indicates that we are using automatically shortened DTMF tones
+    boolean mShortTone;
 
     // indicate if the confirmation from TelephonyFW is pending.
     private boolean mDTMFBurstCnfPending = false;
@@ -405,7 +404,7 @@
         if (DBG) log("DTMFTwelveKeyDialer constructor... this = " + this);
 
         mInCallScreen = parent;
-        mPhone = PhoneApp.getInstance().phone;
+        mPhone = PhoneApp.getPhone();
 
         // The passed-in DTMFTwelveKeyDialerView *should* always be
         // non-null, now that the in-call UI uses only portrait mode.
@@ -450,7 +449,6 @@
             mDialerDrawer.setOnDrawerOpenListener(this);
             mDialerDrawer.setOnDrawerCloseListener(this);
         }
-
     }
 
     /**
@@ -467,12 +465,10 @@
             mDialerDrawer.setOnDrawerOpenListener(null);
             mDialerDrawer.setOnDrawerCloseListener(null);
         }
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
-            mHandler.removeMessages(DTMF_SEND_CNF);
-            synchronized (mDTMFQueue) {
-                mDTMFBurstCnfPending = false;
-                mDTMFQueue.clear();
-            }
+        mHandler.removeMessages(DTMF_SEND_CNF);
+        synchronized (mDTMFQueue) {
+            mDTMFBurstCnfPending = false;
+            mDTMFQueue.clear();
         }
         closeDialer(false);
     }
@@ -513,17 +509,17 @@
 
         // see if we need to play local tones.
         if (mPhone.getContext().getResources().getBoolean(R.bool.allow_local_dtmf_tones)) {
-            mDTMFToneEnabled = Settings.System.getInt(mInCallScreen.getContentResolver(),
+            mLocalToneEnabled = Settings.System.getInt(mInCallScreen.getContentResolver(),
                     Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
         } else {
-            mDTMFToneEnabled = false;
+            mLocalToneEnabled = false;
         }
-        if (DBG) log("- startDialerSession: mDTMFToneEnabled = " + mDTMFToneEnabled);
+        if (DBG) log("- startDialerSession: mLocalToneEnabled = " + mLocalToneEnabled);
 
         // create the tone generator
         // if the mToneGenerator creation fails, just continue without it.  It is
         // a local audio signal, and is not as important as the dtmf tone itself.
-        if (mDTMFToneEnabled) {
+        if (mLocalToneEnabled) {
             synchronized (mToneGeneratorLock) {
                 if (mToneGenerator == null) {
                     try {
@@ -863,55 +859,49 @@
     }
 
     /**
-     * Starts playing a DTMF tone.  Also begins the local tone playback,
-     * if enabled.
-     * The access of this function is package rather than private
-     * since this is being referred from InCallScreen.
-     * InCallScreen calls this function to utilize the DTMF ToneGenerator properties
-     * defined here.
-     * @param tone a tone code from {@link ToneGenerator}
+     * Plays the local tone based the phone type.
      */
-    /* package */ void startDtmfTone(char tone) {
-        if (DBG) log("startDtmfTone()...");
-        mPhone.startDtmf(tone);
-
-        // if local tone playback is enabled, start it.
-        if (mDTMFToneEnabled) {
-            synchronized (mToneGeneratorLock) {
-                if (mToneGenerator == null) {
-                    if (DBG) log("startDtmfTone: mToneGenerator == null, tone: " + tone);
-                } else {
-                    if (DBG) log("starting local tone " + tone);
-                    mToneGenerator.startTone(mToneMap.get(tone));
-                }
-            }
+    public void startTone(char c) {
+        // Only play the tone if it exists.
+        if (!mToneMap.containsKey(c)) {
+            return;
         }
+        // Read the settings as it may be changed by the user during the call
+        mShortTone = TelephonyCapabilities.useShortDtmfTones(mPhone, mPhone.getContext());
+
+        if (DBG) log("startDtmfTone()...");
+
+        // For Short DTMF we need to play the local tone for fixed duration
+        if (mShortTone) {
+            sendShortDtmfToNetwork(c);
+        } else {
+            // Pass as a char to be sent to network
+            Log.i(LOG_TAG, "send long dtmf for " + c);
+            mPhone.startDtmf(c);
+        }
+        startLocalToneIfNeeded(c);
     }
 
     /**
-     * Stops playing the current DTMF tone.
-     *
-     * The ToneStopper class (similar to that in {@link TwelveKeyDialer#mToneStopper})
-     * has been removed in favor of synchronous start / stop calls since tone duration
-     * is now a function of the input.
-     * The acess of this function is package rather than private
-     * since this is being referred from InCallScreen.
-     * InCallScreen calls this function to utilize the DTMF ToneGenerator properties
-     * defined here.
+     * Plays the local tone based the phone type.
      */
-    /* package */ void stopDtmfTone() {
-        if (DBG) log("stopDtmfTone()...");
-        mPhone.stopDtmf();
-
-        // if local tone playback is enabled, stop it.
-        if (DBG) log("trying to stop local tone...");
-        if (mDTMFToneEnabled) {
+    public void startLocalToneIfNeeded(char c) {
+        // if local tone playback is enabled, start it.
+        // Only play the tone if it exists.
+        if (!mToneMap.containsKey(c)) {
+            return;
+        }
+        if (mLocalToneEnabled) {
             synchronized (mToneGeneratorLock) {
                 if (mToneGenerator == null) {
-                    if (DBG) log("stopDtmfTone: mToneGenerator == null");
+                    if (DBG) log("startDtmfTone: mToneGenerator == null, tone: " + c);
                 } else {
-                    if (DBG) log("stopping local tone.");
-                    mToneGenerator.stopTone();
+                    if (DBG) log("starting local tone " + c);
+                    int toneDuration = -1;
+                    if (mShortTone) {
+                        toneDuration = DTMF_DURATION_MS;
+                    }
+                    mToneGenerator.startTone(mToneMap.get(c), toneDuration);
                 }
             }
         }
@@ -932,79 +922,32 @@
     }
 
     /**
-     * Plays the local tone based the phone type.
+     * Stops the local tone based on the phone type.
      */
-    private void startTone(char c) {
-        int phoneType = mPhone.getPhoneType();
-        if (phoneType == Phone.PHONE_TYPE_GSM) {
-            startDtmfTone(c);
-        } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
-            startToneCdma(c);
-        } else {
-            throw new IllegalStateException("Unexpected phone type: " + phoneType);
+    public void stopTone() {
+        if (!mShortTone) {
+            if (DBG) log("stopping remote tone.");
+            mPhone.stopDtmf();
+            stopLocalToneIfNeeded();
         }
     }
 
     /**
      * Stops the local tone based on the phone type.
      */
-    private void stopTone() {
-        int phoneType = mPhone.getPhoneType();
-        if (phoneType == Phone.PHONE_TYPE_GSM) {
-            stopDtmfTone();
-        } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
-            // Cdma case we do stopTone only for Long DTMF Setting
-            if (mDTMFToneType == CallFeaturesSetting.DTMF_TONE_TYPE_LONG) {
-                stopToneCdma();
-            }
-        } else {
-            throw new IllegalStateException("Unexpected phone type: " + phoneType);
-        }
-    }
-
-    /**
-     * Plays tone when the DTMF setting is normal(Short).
-     */
-    void startToneCdma(char tone) {
-        if (DBG) log("startToneCdma('" + tone + "')...");
-
-        // Read the settings as it may be changed by the user during the call
-        mDTMFToneType = Settings.System.getInt(mInCallScreen.getContentResolver(),
-                Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
-                CallFeaturesSetting.DTMF_TONE_TYPE_NORMAL);
-        // For Short DTMF we need to play the local tone for fixed duration
-        if (mDTMFToneType == CallFeaturesSetting.DTMF_TONE_TYPE_NORMAL) {
-            sendShortDtmfToNetwork (tone);
-        } else {
-            // Pass as a char to be sent to network
-            Log.i(LOG_TAG, "send long dtmf for " + tone);
-            mPhone.startDtmf(tone);
-        }
-
-        startLocalToneCdma(tone);
-    }
-
-    /**
-     * Plays local tone for CDMA.
-     */
-    void startLocalToneCdma(char tone) {
-        if (DBG) log("startLocalToneCdma('" + tone + "')..."
-                     + " mDTMFToneEnabled = " + mDTMFToneEnabled + " this = " + this);
-
-        // if local tone playback is enabled, start it.
-        if (mDTMFToneEnabled) {
-            synchronized (mToneGeneratorLock) {
-                if (mToneGenerator == null) {
-                    if (DBG) log("startToneCdma: mToneGenerator == null, tone: " + tone);
-                } else {
-                    if (DBG) log("starting local tone " + tone);
-
-                    // Start the new tone.
-                    int toneDuration = -1;
-                    if (mDTMFToneType == CallFeaturesSetting.DTMF_TONE_TYPE_NORMAL) {
-                        toneDuration = DTMF_DURATION_MS;
+    public void stopLocalToneIfNeeded() {
+        if (!mShortTone) {
+            if (DBG) log("stopping remote tone.");
+            // if local tone playback is enabled, stop it.
+            if (DBG) log("trying to stop local tone...");
+            if (mLocalToneEnabled) {
+                synchronized (mToneGeneratorLock) {
+                    if (mToneGenerator == null) {
+                        if (DBG) log("stopLocalTone: mToneGenerator == null");
+                    } else {
+                        if (DBG) log("stopping local tone.");
+                        mToneGenerator.stopTone();
                     }
-                    mToneGenerator.startTone(mToneMap.get(tone), toneDuration);
                 }
             }
         }
@@ -1031,35 +974,6 @@
     }
 
     /**
-     * Stops the dtmf from being sent over the network for Long DTMF case
-     * and stops local DTMF key feedback tone.
-     */
-    private void stopToneCdma() {
-        if (DBG) log("stopping remote tone.");
-
-        mPhone.stopDtmf();
-        stopLocalToneCdma();
-    }
-
-    /**
-     * Stops the local dtmf tone.
-     */
-    void stopLocalToneCdma() {
-        // if local tone playback is enabled, stop it.
-        if (DBG) log("trying to stop local tone...");
-        if (mDTMFToneEnabled) {
-            synchronized (mToneGeneratorLock) {
-                if (mToneGenerator == null) {
-                    if (DBG) log("stopLocalToneCdma: mToneGenerator == null");
-                } else {
-                    if (DBG) log("stopping local tone.");
-                    mToneGenerator.stopTone();
-                }
-            }
-        }
-    }
-
-    /**
      * Handles Burst Dtmf Confirmation from the Framework.
      */
     void handleBurstDtmfConfirmation() {
diff --git a/phone/src/com/android/phone2/DeleteFdnContactScreen.java b/phone/src/com/android/phone2/DeleteFdnContactScreen.java
index b8eb8dc..74e0624 100644
--- a/phone/src/com/android/phone2/DeleteFdnContactScreen.java
+++ b/phone/src/com/android/phone2/DeleteFdnContactScreen.java
@@ -93,16 +93,20 @@
         mName =  intent.getStringExtra(INTENT_EXTRA_NAME);
         mNumber =  intent.getStringExtra(INTENT_EXTRA_NUMBER);
 
-        if (TextUtils.isEmpty(mName)) {
+        if (TextUtils.isEmpty(mNumber)) {
             finish();
         }
     }
 
     private void deleteContact() {
         StringBuilder buf = new StringBuilder();
-        buf.append("tag='");
-        buf.append(mName);
-        buf.append("' AND number='");
+        if (TextUtils.isEmpty(mName)) {
+            buf.append("number='");
+        } else {
+            buf.append("tag='");
+            buf.append(mName);
+            buf.append("' AND number='");
+        }
         buf.append(mNumber);
         buf.append("' AND pin2='");
         buf.append(mPin2);
diff --git a/phone/src/com/android/phone2/EditFdnContactScreen.java b/phone/src/com/android/phone2/EditFdnContactScreen.java
index 6dcf596..c17cc9a 100644
--- a/phone/src/com/android/phone2/EditFdnContactScreen.java
+++ b/phone/src/com/android/phone2/EditFdnContactScreen.java
@@ -205,9 +205,7 @@
         mName =  intent.getStringExtra(INTENT_EXTRA_NAME);
         mNumber =  intent.getStringExtra(INTENT_EXTRA_NUMBER);
 
-        if (TextUtils.isEmpty(mName) && TextUtils.isEmpty(mNumber)) {
-            mAddContact = true;
-        }
+        mAddContact = TextUtils.isEmpty(mNumber);
     }
 
     /**
diff --git a/phone/src/com/android/phone2/EditPhoneNumberPreference.java b/phone/src/com/android/phone2/EditPhoneNumberPreference.java
index 56d32a2..92af9da 100644
--- a/phone/src/com/android/phone2/EditPhoneNumberPreference.java
+++ b/phone/src/com/android/phone2/EditPhoneNumberPreference.java
@@ -187,7 +187,7 @@
     @Override
     protected void onBindDialogView(View view) {
         // default the button clicked to be the cancel button.
-        mButtonClicked = DialogInterface.BUTTON2;
+        mButtonClicked = DialogInterface.BUTTON_NEGATIVE;
 
         super.onBindDialogView(view);
 
@@ -307,7 +307,7 @@
     @Override
     public void onClick(DialogInterface dialog, int which) {
         // The neutral button (button3) is always the toggle.
-        if ((mConfirmationMode == CM_ACTIVATION) && (which == DialogInterface.BUTTON3)) {
+        if ((mConfirmationMode == CM_ACTIVATION) && (which == DialogInterface.BUTTON_NEUTRAL)) {
             //flip the toggle if we are in the correct mode.
             setToggled(!isToggled());
         }
@@ -321,8 +321,8 @@
     // phone numbers and calling the close action listener.
     protected void onDialogClosed(boolean positiveResult) {
         // A positive result is technically either button1 or button3.
-        if ((mButtonClicked == DialogInterface.BUTTON1) ||
-                (mButtonClicked == DialogInterface.BUTTON3)){
+        if ((mButtonClicked == DialogInterface.BUTTON_POSITIVE) ||
+                (mButtonClicked == DialogInterface.BUTTON_NEUTRAL)){
             setPhoneNumber(getEditText().getText().toString());
             super.onDialogClosed(positiveResult);
             setText(getStringValue());
diff --git a/phone/src/com/android/phone2/EmergencyCallHandler.java b/phone/src/com/android/phone2/EmergencyCallHandler.java
index 2181ae4..de2129a 100644
--- a/phone/src/com/android/phone2/EmergencyCallHandler.java
+++ b/phone/src/com/android/phone2/EmergencyCallHandler.java
@@ -26,7 +26,6 @@
 import android.os.Message;
 import android.provider.Settings;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 import android.telephony.ServiceState;
 import android.view.WindowManager;
 
@@ -107,7 +106,7 @@
         super.onCreate(icicle);
         
         // setup the phone and get the retry count embedded in the intent.
-        Phone phone = PhoneFactory.getDefaultPhone();
+        Phone phone = PhoneApp.getPhone();
         int retryCount = getIntent().getIntExtra(EMERGENCY_CALL_RETRY_KEY, INITIAL_ATTEMPT);
         
         // create a new message object.
diff --git a/phone/src/com/android/phone2/EmergencyCallbackModeExitDialog.java b/phone/src/com/android/phone2/EmergencyCallbackModeExitDialog.java
index 54bfc5c..d36d5d8 100644
--- a/phone/src/com/android/phone2/EmergencyCallbackModeExitDialog.java
+++ b/phone/src/com/android/phone2/EmergencyCallbackModeExitDialog.java
@@ -40,7 +40,6 @@
 import android.util.Log;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 
@@ -92,7 +91,7 @@
         waitForConnectionCompleteThread.start();
 
         // Register ECM timer reset notfication
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         mPhone.registerForEcmTimerReset(mTimerResetHandler, ECM_TIMER_RESET, null);
 
         // Register receiver for intent closing the dialog
diff --git a/phone/src/com/android/phone2/EnableFdnScreen.java b/phone/src/com/android/phone2/EnableFdnScreen.java
index 6a68679..bb3d2c7 100644
--- a/phone/src/com/android/phone2/EnableFdnScreen.java
+++ b/phone/src/com/android/phone2/EnableFdnScreen.java
@@ -31,7 +31,6 @@
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 /**
  * UI to enable/disable FDN.
@@ -68,7 +67,7 @@
         setContentView(R.layout.enable_fdn_screen);
         setupView();
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         mEnable = !mPhone.getIccCard().getIccFdnEnabled();
 
         int id = mEnable ? R.string.enable_fdn : R.string.disable_fdn;
@@ -78,7 +77,7 @@
     @Override
     protected void onResume() {
         super.onResume();
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
     }
 
     private void setupView() {
diff --git a/phone/src/com/android/phone2/EnableIccPinScreen.java b/phone/src/com/android/phone2/EnableIccPinScreen.java
index 3bd4e46..9ad7b03 100644
--- a/phone/src/com/android/phone2/EnableIccPinScreen.java
+++ b/phone/src/com/android/phone2/EnableIccPinScreen.java
@@ -31,7 +31,6 @@
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 /**
  * UI to enable/disable the ICC PIN.
@@ -68,7 +67,7 @@
         setContentView(R.layout.enable_sim_pin_screen);
         setupView();
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         mEnable = !mPhone.getIccCard().getIccLockEnabled();
 
         int id = mEnable ? R.string.enable_sim_pin : R.string.disable_sim_pin;
diff --git a/phone/src/com/android/phone2/FakePhoneActivity.java b/phone/src/com/android/phone2/FakePhoneActivity.java
index 67d9350..141b54e 100644
--- a/phone/src/com/android/phone2/FakePhoneActivity.java
+++ b/phone/src/com/android/phone2/FakePhoneActivity.java
@@ -54,10 +54,10 @@
                     }
                 });
 
-        mRadioControl = PhoneApp.getInstance().phone.getSimulatedRadioControl();
+        mRadioControl = PhoneApp.getPhone().getSimulatedRadioControl();
 
         Log.i(TAG, "- PhoneApp.getInstance(): " + PhoneApp.getInstance());
-        Log.i(TAG, "- PhoneApp.getInstance().phone: " + PhoneApp.getInstance().phone);
+        Log.i(TAG, "- PhoneApp.getPhone(): " + PhoneApp.getPhone());
         Log.i(TAG, "- mRadioControl: " + mRadioControl);
     }
 
diff --git a/phone/src/com/android/phone2/FdnSetting.java b/phone/src/com/android/phone2/FdnSetting.java
index 5dbece0..eeedc6f 100644
--- a/phone/src/com/android/phone2/FdnSetting.java
+++ b/phone/src/com/android/phone2/FdnSetting.java
@@ -29,7 +29,6 @@
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 /**
  * FDN settings UI for the Phone app.
@@ -384,7 +383,7 @@
 
         addPreferencesFromResource(R.xml.fdn_setting);
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
 
         //get UI object references
         PreferenceScreen prefSet = getPreferenceScreen();
@@ -413,7 +412,7 @@
     @Override
     protected void onResume() {
         super.onResume();
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         updateEnableFDN();
     }
 
diff --git a/phone/src/com/android/phone2/GsmUmtsCallOptions.java b/phone/src/com/android/phone2/GsmUmtsCallOptions.java
index a87d2b9..ec1b85a 100644
--- a/phone/src/com/android/phone2/GsmUmtsCallOptions.java
+++ b/phone/src/com/android/phone2/GsmUmtsCallOptions.java
@@ -23,7 +23,6 @@
 import android.preference.PreferenceScreen;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 public class GsmUmtsCallOptions extends PreferenceActivity {
     private static final String LOG_TAG = "GsmUmtsCallOptions";
@@ -35,7 +34,7 @@
 
         addPreferencesFromResource(R.xml.gsm_umts_call_options);
 
-        if (PhoneFactory.getDefaultPhone().getPhoneType() != Phone.PHONE_TYPE_GSM) {
+        if (PhoneApp.getPhone().getPhoneType() != Phone.PHONE_TYPE_GSM) {
             //disable the entire screen
             getPreferenceScreen().setEnabled(false);
         }
diff --git a/phone/src/com/android/phone2/GsmUmtsOptions.java b/phone/src/com/android/phone2/GsmUmtsOptions.java
index 99f36a4..6593a52 100644
--- a/phone/src/com/android/phone2/GsmUmtsOptions.java
+++ b/phone/src/com/android/phone2/GsmUmtsOptions.java
@@ -16,7 +16,6 @@
 
 package com.android.phone2;
 
-import android.os.Bundle;
 import android.preference.CheckBoxPreference;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
@@ -28,7 +27,8 @@
 /**
  * List of Network-specific settings screens.
  */
-public class GsmUmtsOptions extends PreferenceActivity {
+public class GsmUmtsOptions {
+    private static final String LOG_TAG = "GsmUmtsOptions";
 
     private PreferenceScreen mButtonAPNExpand;
     private PreferenceScreen mButtonOperatorSelectionExpand;
@@ -37,30 +37,39 @@
     private static final String BUTTON_APN_EXPAND_KEY = "button_apn_key";
     private static final String BUTTON_OPERATOR_SELECTION_EXPAND_KEY = "button_carrier_sel_key";
     private static final String BUTTON_PREFER_2G_KEY = "button_prefer_2g_key";
+    private PreferenceActivity mPrefActivity;
+    private PreferenceScreen mPrefScreen;
 
+    public GsmUmtsOptions(PreferenceActivity prefActivity, PreferenceScreen prefScreen) {
+        mPrefActivity = prefActivity;
+        mPrefScreen = prefScreen;
+        create();
+    }
 
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        addPreferencesFromResource(R.xml.gsm_umts_options);
-        PreferenceScreen prefSet = getPreferenceScreen();
-        mButtonAPNExpand = (PreferenceScreen) prefSet.findPreference(BUTTON_APN_EXPAND_KEY);
+    protected void create() {
+        mPrefActivity.addPreferencesFromResource(R.xml.gsm_umts_options);
+        mButtonAPNExpand = (PreferenceScreen) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
         mButtonOperatorSelectionExpand =
-                (PreferenceScreen) prefSet.findPreference(BUTTON_OPERATOR_SELECTION_EXPAND_KEY);
-        mButtonPrefer2g = (CheckBoxPreference) prefSet.findPreference(BUTTON_PREFER_2G_KEY);
+                (PreferenceScreen) mPrefScreen.findPreference(BUTTON_OPERATOR_SELECTION_EXPAND_KEY);
+        mButtonPrefer2g = (CheckBoxPreference) mPrefScreen.findPreference(BUTTON_PREFER_2G_KEY);
         if (PhoneFactory.getDefaultPhone().getPhoneType() != Phone.PHONE_TYPE_GSM) {
+            log("Not a GSM phone");
             mButtonAPNExpand.setEnabled(false);
             mButtonOperatorSelectionExpand.setEnabled(false);
             mButtonPrefer2g.setEnabled(false);
         }
     }
 
-    @Override
-    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+    public boolean preferenceTreeClick(Preference preference) {
         if (preference.getKey().equals(BUTTON_PREFER_2G_KEY)) {
+            log("preferenceTreeClick: return true");
             return true;
         }
+        log("preferenceTreeClick: return false");
         return false;
     }
+
+    protected void log(String s) {
+        android.util.Log.d(LOG_TAG, s);
+    }
 }
diff --git a/phone/src/com/android/phone2/IccNetworkDepersonalizationPanel.java b/phone/src/com/android/phone2/IccNetworkDepersonalizationPanel.java
index 390d47e..27cfce1 100644
--- a/phone/src/com/android/phone2/IccNetworkDepersonalizationPanel.java
+++ b/phone/src/com/android/phone2/IccNetworkDepersonalizationPanel.java
@@ -35,7 +35,6 @@
 import android.widget.TextView;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 /**
  * "SIM network unlock" PIN entry screen.
@@ -149,7 +148,7 @@
         mStatusPanel = (LinearLayout) findViewById(R.id.status_panel);
         mStatusText = (TextView) findViewById(R.id.status_text);
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
     }
 
     @Override
diff --git a/phone/src/com/android/phone2/InCallControlState.java b/phone/src/com/android/phone2/InCallControlState.java
index d154d55..17bc4c3 100644
--- a/phone/src/com/android/phone2/InCallControlState.java
+++ b/phone/src/com/android/phone2/InCallControlState.java
@@ -102,20 +102,17 @@
         final boolean hasHoldingCall = !mPhone.getBackgroundCall().isIdle();
 
         // Manage conference:
-        int phoneType = mPhone.getPhoneType();
-        if (phoneType == Phone.PHONE_TYPE_GSM) {
+        if (TelephonyCapabilities.supportsConferenceCallManagement(mPhone)) {
             // This item is visible only if the foreground call is a
             // conference call, and it's enabled unless the "Manage
             // conference" UI is already up.
             manageConferenceVisible = PhoneUtils.isConferenceCall(fgCall);
             manageConferenceEnabled =
                     manageConferenceVisible && !mInCallScreen.isManageConferenceMode();
-        } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
-            // CDMA has no concept of managing a conference call.
+        } else {
+            // This device has no concept of managing a conference call.
             manageConferenceVisible = false;
             manageConferenceEnabled = false;
-        } else {
-            throw new IllegalStateException("Unexpected phone type: " + phoneType);
         }
 
         // "Add call":
@@ -141,20 +138,14 @@
 
         // "Mute": only enabled when the foreground call is ACTIVE.
         // (It's meaningless while on hold, or while DIALING/ALERTING.)
-        // Also disabled (on CDMA devices) during emergency calls.
-        if (phoneType == Phone.PHONE_TYPE_CDMA) {
-            Connection c = fgCall.getLatestConnection();
-            boolean isEmergencyCall = false;
-            if (c != null) isEmergencyCall = PhoneNumberUtils.isEmergencyNumber(c.getAddress());
-
-            if (isEmergencyCall) { // disable "Mute" item
-                canMute = false;
-                muteIndicatorOn = false;
-            } else {
-                canMute = hasActiveForegroundCall;
-                muteIndicatorOn = PhoneUtils.getMute(mPhone);
-            }
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        // It's also explicitly disabled during emergency calls.
+        Connection c = fgCall.getLatestConnection();
+        boolean isEmergencyCall = false;
+        if (c != null) isEmergencyCall = PhoneNumberUtils.isEmergencyNumber(c.getAddress());
+        if (isEmergencyCall) { // disable "Mute" item
+            canMute = false;
+            muteIndicatorOn = false;
+        } else {
             canMute = hasActiveForegroundCall;
             muteIndicatorOn = PhoneUtils.getMute(mPhone);
         }
@@ -168,8 +159,8 @@
         dialpadVisible = mInCallScreen.isDialerOpened();
 
         // "Hold:
-        if (phoneType == Phone.PHONE_TYPE_GSM) {
-            // GSM phones have the concept of "Hold" and "Unhold".
+        if (TelephonyCapabilities.supportsHoldAndUnhold(mPhone)) {
+            // This phone has the concept of explicit "Hold" and "Unhold" actions.
             supportsHold = true;
             // "On hold" means that there's a holding call and
             // *no* foreground call.  (If there *is* a foreground call,
@@ -180,8 +171,8 @@
             boolean okToHold = hasActiveForegroundCall && !hasHoldingCall;
             boolean okToUnhold = onHold;
             canHold = okToHold || okToUnhold;
-        } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
-            // CDMA has no concept of "putting a call on hold."
+        } else {
+            // This device has no concept of "putting a call on hold."
             supportsHold = false;
             onHold = false;
             canHold = false;
diff --git a/phone/src/com/android/phone2/InCallMenu.java b/phone/src/com/android/phone2/InCallMenu.java
index d6ad635..9b04b38 100755
--- a/phone/src/com/android/phone2/InCallMenu.java
+++ b/phone/src/com/android/phone2/InCallMenu.java
@@ -210,12 +210,11 @@
         //
 
         // Row 0:
-        // This usually has "Show/Hide dialpad", but that gets replaced by
-        // "Manage conference" if a conference call is active.
+        // This usually has "Show/Hide dialpad", but that might be replaced by
+        // "Manage conference" if a conference call is active (but only
+        // on phones that support "Manage conference" in the first place.)
         PhoneApp app = PhoneApp.getInstance();
-        // As managing conference is only valid for GSM and not for CDMA
-        int phoneType = app.phone.getPhoneType();
-        if (phoneType == Phone.PHONE_TYPE_GSM) {
+        if (TelephonyCapabilities.supportsConferenceCallManagement(app.phone)) {
             mInCallMenuView.addItemView(mManageConference, 0);
         }
         mInCallMenuView.addItemView(mShowDialpad, 0);
@@ -229,16 +228,19 @@
         // Row 2:
         // In this row we see *either*  bluetooth/speaker/mute/hold
         // *or* answerAndHold/answerAndEnd, but never all 6 together.
-        // For CDMA only Answer or Ignore option is valid for a Call Waiting scenario
-        if (phoneType == Phone.PHONE_TYPE_CDMA) {
-            mInCallMenuView.addItemView(mAnswer, 2);
-            mInCallMenuView.addItemView(mIgnore, 2);
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+        if (TelephonyCapabilities.supportsHoldAndUnhold(app.phone)) {
             mInCallMenuView.addItemView(mHold, 2);
+        }
+        // For phones that allow explicit "Answer & Hold" and "Answer &
+        // End" actions for a call-waiting call, provide menu items for
+        // those.  Otherwise, just provide basic "Answer" and "Ignore"
+        // items.
+        if (TelephonyCapabilities.supportsAnswerAndHold(app.phone)) {
             mInCallMenuView.addItemView(mAnswerAndHold, 2);
             mInCallMenuView.addItemView(mAnswerAndEnd, 2);
         } else {
-            throw new IllegalStateException("Unexpected phone type: " + phoneType);
+            mInCallMenuView.addItemView(mAnswer, 2);
+            mInCallMenuView.addItemView(mIgnore, 2);
         }
         mInCallMenuView.addItemView(mMute, 2);
         mInCallMenuView.addItemView(mSpeaker, 2);
@@ -275,7 +277,8 @@
         final boolean hasHoldingCall = !phone.getBackgroundCall().isIdle();
 
         // For OTA call, only show dialpad, endcall, speaker, and mute menu items
-        if (hasActiveCall && (PhoneApp.getInstance().isOtaCallInActiveState())) {
+        if (hasActiveCall && TelephonyCapabilities.supportsOtasp(phone) &&
+                (PhoneApp.getInstance().isOtaCallInActiveState())) {
             mAnswerAndHold.setVisible(false);
             mAnswerAndHold.setEnabled(false);
             mAnswerAndEnd.setVisible(false);
@@ -316,37 +319,35 @@
 
         // Special cases when an incoming call is ringing.
         if (hasRingingCall) {
-            // In the "call waiting" state, show ONLY the "answer & end"
-            // and "answer & hold" buttons, and nothing else.
-            // TODO: be sure to test this for "only one line in use and it's
-            // active" AND for "only one line in use and it's on hold".
             if (hasActiveCall && !hasHoldingCall) {
-                int phoneType = phone.getPhoneType();
-                // For CDMA only make "Answer" and "Ignore" visible
-                if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                    mAnswer.setVisible(true);
-                    mAnswer.setEnabled(true);
-                    mIgnore.setVisible(true);
-                    mIgnore.setEnabled(true);
-
-                    // Explicitly remove GSM menu items
-                    mAnswerAndHold.setVisible(false);
-                    mAnswerAndEnd.setVisible(false);
-                } else if (phoneType == Phone.PHONE_TYPE_GSM) {
+                // In the "call waiting" state, some devices allow separate
+                // "Answer & End" and "Answer & Hold" actions, and other
+                // devices just get basic "Answer" and "Ignore" actions.
+                if (TelephonyCapabilities.supportsAnswerAndHold(phone)) {
                     mAnswerAndHold.setVisible(true);
                     mAnswerAndHold.setEnabled(true);
                     mAnswerAndEnd.setVisible(true);
                     mAnswerAndEnd.setEnabled(true);
 
-                    // Explicitly remove CDMA menu items
+                    // Explicitly remove unused items
                     mAnswer.setVisible(false);
                     mIgnore.setVisible(false);
-
-                    mManageConference.setVisible(false);
                 } else {
-                    throw new IllegalStateException("Unexpected phone type: " + phoneType);
+                    // Just make the basic "Answer" and "Ignore" visible
+                    mAnswer.setVisible(true);
+                    mAnswer.setEnabled(true);
+                    mIgnore.setVisible(true);
+                    mIgnore.setEnabled(true);
+
+                    // Explicitly remove unused items
+                    mAnswerAndHold.setVisible(false);
+                    mAnswerAndEnd.setVisible(false);
                 }
 
+                // And regardless of the "Answer & Hold" capability of the
+                // current phone, disable everything else that's irrelevant to
+                // the call-waiting state.
+                mManageConference.setVisible(false);
                 mShowDialpad.setVisible(false);
                 mEndCall.setVisible(false);
                 mAddCall.setVisible(false);
diff --git a/phone/src/com/android/phone2/InCallScreen.java b/phone/src/com/android/phone2/InCallScreen.java
index 0ff451f..e0e1024 100755
--- a/phone/src/com/android/phone2/InCallScreen.java
+++ b/phone/src/com/android/phone2/InCallScreen.java
@@ -52,12 +52,14 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.widget.EditText;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.SlidingDrawer;
 import android.widget.TextView;
@@ -302,7 +304,7 @@
     private boolean mIsDestroyed = false;
     private boolean mIsForegroundActivity = false;
 
-    // For use with CDMA Pause/Wait dialogs
+    // For use with Pause/Wait dialogs
     private String mPostDialStrAfterPause;
     private boolean mPauseInProgress = false;
 
@@ -567,42 +569,6 @@
 
         initInCallScreen();
 
-        // Create the dtmf dialer.  The dialer view we use depends on the
-        // current platform:
-        //
-        // - On non-prox-sensor devices, it's the dialpad contained inside
-        //   a SlidingDrawer widget (see dtmf_twelve_key_dialer.xml).
-        //
-        // - On "full touch UI" devices, it's the compact non-sliding
-        //   dialpad that appears on the upper half of the screen,
-        //   above the main cluster of InCallTouchUi buttons
-        //   (see non_drawer_dialpad.xml).
-        //
-        // TODO: These should both be ViewStubs, and right here we should
-        // inflate one or the other.  (Also, while doing that, let's also
-        // move this block of code over to initInCallScreen().)
-        //
-        SlidingDrawer dialerDrawer;
-        if (isTouchUiEnabled()) {
-            // This is a "full touch" device.
-            mDialerView = (DTMFTwelveKeyDialerView) findViewById(R.id.non_drawer_dtmf_dialer);
-            if (DBG) log("- Full touch device!  Found dialerView: " + mDialerView);
-            dialerDrawer = null;  // No SlidingDrawer used on this device.
-        } else {
-            // Use the old-style dialpad contained within the SlidingDrawer.
-            mDialerView = (DTMFTwelveKeyDialerView) findViewById(R.id.dtmf_dialer);
-            if (DBG) log("- Using SlidingDrawer-based dialpad.  Found dialerView: " + mDialerView);
-            dialerDrawer = (SlidingDrawer) findViewById(R.id.dialer_container);
-            if (DBG) log("  ...and the SlidingDrawer: " + dialerDrawer);
-        }
-        // Sanity-check that (regardless of the device) at least the
-        // dialer view is present:
-        if (mDialerView == null) {
-            Log.e(LOG_TAG, "onCreate: couldn't find dialerView", new IllegalStateException());
-        }
-        // Finally, create the DTMFTwelveKeyDialer instance.
-        mDialer = new DTMFTwelveKeyDialer(this, mDialerView, dialerDrawer);
-
         registerForPhoneStates();
 
         // No need to change wake state here; that happens in onResume() when we
@@ -684,6 +650,7 @@
 
         // Check for any failures that happened during onCreate() or onNewIntent().
         if (DBG) log("- onResume: initial status = " + mInCallInitialStatus);
+        boolean handledStartupError = false;
         if (mInCallInitialStatus != InCallInitStatus.SUCCESS) {
             if (DBG) log("- onResume: failure during startup: " + mInCallInitialStatus);
 
@@ -691,6 +658,7 @@
             // something more specific to let the user deal with the
             // problem.
             handleStartupError(mInCallInitialStatus);
+            handledStartupError = true;
 
             // But it *is* OK to continue with the rest of onResume(),
             // since any further setup steps (like updateScreen() and the
@@ -710,10 +678,8 @@
 
         takeKeyEvents(true);
 
-        boolean phoneIsCdma = (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
-
         boolean inOtaCall = false;
-        if (phoneIsCdma) {
+        if (TelephonyCapabilities.supportsOtasp(mPhone)) {
             inOtaCall = initOtaState();
         }
         if (!inOtaCall) {
@@ -729,13 +695,38 @@
 
         InCallInitStatus status = syncWithPhoneState();
         if (status != InCallInitStatus.SUCCESS) {
-            if (DBG) log("- syncWithPhoneState failed! status = " + status);
+            if (DBG) log("- onResume: syncWithPhoneState failed! status = " + status);
             // Couldn't update the UI, presumably because the phone is totally
-            // idle.  But don't endInCallScreenSession immediately, since we might still
-            // have an error dialog up that the user needs to see.
-            // (And in that case, the error dialog is responsible for calling
-            // endInCallScreenSession when the user dismisses it.)
-        } else if (phoneIsCdma) {
+            // idle.
+
+            if (handledStartupError) {
+                // Do NOT bail out of the in-call UI, since there's
+                // presumably a dialog visible right now (see the call to
+                // handleStartupError() above.)
+                //
+                // In this case, stay here for now, and we'll eventually
+                // leave the InCallScreen when the user presses the
+                // dialog's OK button (see bailOutAfterErrorDialog()).
+                Log.i(LOG_TAG, "  ==> syncWithPhoneState failed, but staying here anyway.");
+            } else {
+                // The phone is idle, and we did NOT handle a
+                // startup error during this pass thru onResume.
+                //
+                // This basically means that we're being resumed because of
+                // some action *other* than a new intent.  (For example,
+                // the user pressing POWER to wake up the device, causing
+                // the InCallScreen to come back to the foreground.)
+                //
+                // In this scenario we do NOT want to stay here on the
+                // InCallScreen: we're not showing any useful info to the
+                // user (like a dialog), and the in-call UI itself is
+                // useless if there's no active call.  So bail out.
+                Log.i(LOG_TAG, "  ==> syncWithPhoneState failed; bailing out!");
+                dismissAllDialogs();
+                endInCallScreenSession();
+                return;
+            }
+        } else if (TelephonyCapabilities.supportsOtasp(mPhone)) {
             if (mInCallScreenMode == InCallScreenMode.OTA_NORMAL ||
                     mInCallScreenMode == InCallScreenMode.OTA_ENDED) {
                 mDialer.setHandleVisible(false);
@@ -1034,26 +1025,18 @@
         if (!mRegisteredForPhoneStates) {
             mPhone.registerForPreciseCallStateChanged(mHandler, PHONE_STATE_CHANGED, null);
             mPhone.registerForDisconnect(mHandler, PHONE_DISCONNECT, null);
-            int phoneType = mPhone.getPhoneType();
-            if (phoneType == Phone.PHONE_TYPE_GSM) {
-                mPhone.registerForMmiInitiate(mHandler, PhoneApp.MMI_INITIATE, null);
+            mPhone.registerForMmiInitiate(mHandler, PhoneApp.MMI_INITIATE, null);
 
-                // register for the MMI complete message.  Upon completion,
-                // PhoneUtils will bring up a system dialog instead of the
-                // message display class in PhoneUtils.displayMMIComplete().
-                // We'll listen for that message too, so that we can finish
-                // the activity at the same time.
-                mPhone.registerForMmiComplete(mHandler, PhoneApp.MMI_COMPLETE, null);
-            } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                if (DBG) log("Registering for Call Waiting.");
-                mPhone.registerForCallWaiting(mHandler, PHONE_CDMA_CALL_WAITING, null);
-            } else {
-                throw new IllegalStateException("Unexpected phone type: " + phoneType);
-            }
-
+            // register for the MMI complete message.  Upon completion,
+            // PhoneUtils will bring up a system dialog instead of the
+            // message display class in PhoneUtils.displayMMIComplete().
+            // We'll listen for that message too, so that we can finish
+            // the activity at the same time.
+            mPhone.registerForMmiComplete(mHandler, PhoneApp.MMI_COMPLETE, null);
+            mPhone.registerForCallWaiting(mHandler, PHONE_CDMA_CALL_WAITING, null);
             mPhone.setOnPostDialCharacter(mHandler, POST_ON_DIAL_CHARS, null);
             mPhone.registerForSuppServiceFailed(mHandler, SUPP_SERVICE_FAILED, null);
-            if (phoneType == Phone.PHONE_TYPE_CDMA) {
+            if (TelephonyCapabilities.supportsOtasp(mPhone)) {
                 mPhone.registerForCdmaOtaStatusChange(mHandler, EVENT_OTA_PROVISION_CHANGE, null);
             }
             mRegisteredForPhoneStates = true;
@@ -1072,6 +1055,11 @@
 
     /* package */ void updateAfterRadioTechnologyChange() {
         if (DBG) Log.d(LOG_TAG, "updateAfterRadioTechnologyChange()...");
+
+        // Reset the call screen since the calls cannot be transferred
+        // across radio technologies.
+        resetInCallScreenMode();
+
         // Unregister for all events from the old obsolete phone
         unregisterForPhoneStates();
 
@@ -1132,7 +1120,7 @@
         // InCallScreen UI started with Intent of ACTION_SHOW_ACTIVATION
         // to show OTA Activation screen at power up.
         if ((action.equals(ACTION_SHOW_ACTIVATION))
-                && ((mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA))) {
+                && (TelephonyCapabilities.supportsOtasp(mPhone))) {
             setInCallScreenMode(InCallScreenMode.OTA_NORMAL);
             if ((app.cdmaOtaProvisionData != null)
                     && (!app.cdmaOtaProvisionData.isOtaCallIntentProcessed)) {
@@ -1238,6 +1226,42 @@
 
         // Helper class to run the "Manage conference" UI
         mManageConferenceUtils = new ManageConferenceUtils(this, mPhone);
+
+        // Create the dtmf dialer.  The dialer view we use depends on the
+        // current platform:
+        //
+        // - On non-prox-sensor devices, it's the dialpad contained inside
+        //   a SlidingDrawer widget (see dtmf_twelve_key_dialer.xml).
+        //
+        // - On "full touch UI" devices, it's the compact non-sliding
+        //   dialpad that appears on the upper half of the screen,
+        //   above the main cluster of InCallTouchUi buttons
+        //   (see non_drawer_dialpad.xml).
+        //
+        SlidingDrawer dialerDrawer;
+        if (isTouchUiEnabled()) {
+            // This is a "full touch" device.
+            ViewStub stub = (ViewStub)findViewById(R.id.non_drawer_dialpad_stub);
+            stub.inflate();
+            mDialerView = (DTMFTwelveKeyDialerView) findViewById(R.id.non_drawer_dtmf_dialer);
+            if (DBG) log("- Full touch device!  Found dialerView: " + mDialerView);
+            dialerDrawer = null;  // No SlidingDrawer used on this device.
+        } else {
+            // Use the old-style dialpad contained within the SlidingDrawer.
+            ViewStub stub = (ViewStub)findViewById(R.id.dtmf_dialer_stub);
+            stub.inflate();
+            mDialerView = (DTMFTwelveKeyDialerView) findViewById(R.id.dtmf_dialer);
+            if (DBG) log("- Using SlidingDrawer-based dialpad.  Found dialerView: " + mDialerView);
+            dialerDrawer = (SlidingDrawer) findViewById(R.id.dialer_container);
+            if (DBG) log("  ...and the SlidingDrawer: " + dialerDrawer);
+        }
+        // Sanity-check that (regardless of the device) at least the
+        // dialer view is present:
+        if (mDialerView == null) {
+            Log.e(LOG_TAG, "onCreate: couldn't find dialerView", new IllegalStateException());
+        }
+        // Finally, create the DTMFTwelveKeyDialer instance.
+        mDialer = new DTMFTwelveKeyDialer(this, mDialerView, dialerDrawer);
     }
 
     /**
@@ -2034,17 +2058,19 @@
             if (VDBG) log("handlePostOnDialChar: state = " +
                     state + ", ch = " + ch);
 
-            int phoneType = mPhone.getPhoneType();
             switch (state) {
                 case STARTED:
-                    if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                        mDialer.stopLocalToneCdma();
-                        if (mPauseInProgress) {
-                            showPausePromptDialogCDMA(c, mPostDialStrAfterPause);
-                        }
-                        mPauseInProgress = false;
-                        mDialer.startLocalToneCdma(ch);
+                    mDialer.stopLocalToneIfNeeded();
+                    if (mPauseInProgress) {
+                        /**
+                         * Note that on some devices, this will never happen,
+                         * because we will not ever enter the PAUSE state.
+                         */
+                        showPausePromptDialog(c, mPostDialStrAfterPause);
                     }
+                    mPauseInProgress = false;
+                    mDialer.startLocalToneIfNeeded(ch);
+
                     // TODO: is this needed, now that you can't actually
                     // type DTMF chars or dial directly from here?
                     // If so, we'd need to yank you out of the in-call screen
@@ -2053,35 +2079,28 @@
                     break;
 
                 case WAIT:
+                    // wait shows a prompt.
                     if (DBG) log("handlePostOnDialChars: show WAIT prompt...");
+                    mDialer.stopLocalToneIfNeeded();
                     String postDialStr = c.getRemainingPostDialString();
-                    if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                        mDialer.stopLocalToneCdma();
-                        showWaitPromptDialogCDMA(c, postDialStr);
-                    } else if (phoneType == Phone.PHONE_TYPE_GSM) {
-                        showWaitPromptDialogGSM(c, postDialStr);
-                    } else {
-                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
-                    }
+                    showWaitPromptDialog(c, postDialStr);
                     break;
 
                 case WILD:
                     if (DBG) log("handlePostOnDialChars: show WILD prompt");
+                    mDialer.stopLocalToneIfNeeded();
                     showWildPromptDialog(c);
                     break;
 
                 case COMPLETE:
-                    if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                        mDialer.stopLocalToneCdma();
-                    }
+                    mDialer.stopLocalToneIfNeeded();
                     break;
 
                 case PAUSE:
-                    if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                        mPostDialStrAfterPause = c.getRemainingPostDialString();
-                        mDialer.stopLocalToneCdma();
-                        mPauseInProgress = true;
-                    }
+                    // pauses for a brief period of time then continue dialing.
+                    mDialer.stopLocalToneIfNeeded();
+                    mPostDialStrAfterPause = c.getRemainingPostDialString();
+                    mPauseInProgress = true;
                     break;
 
                 default:
@@ -2090,52 +2109,12 @@
         }
     }
 
-    private void showWaitPromptDialogGSM(final Connection c, String postDialStr) {
-        if (DBG) log("showWaitPromptDialogGSM: '" + postDialStr + "'...");
-
-        Resources r = getResources();
-        StringBuilder buf = new StringBuilder();
-        buf.append(r.getText(R.string.wait_prompt_str));
-        buf.append(postDialStr);
-
-        // if (DBG) log("- mWaitPromptDialog = " + mWaitPromptDialog);
-        if (mWaitPromptDialog != null) {
-            if (DBG) log("- DISMISSING mWaitPromptDialog.");
-            mWaitPromptDialog.dismiss();  // safe even if already dismissed
-            mWaitPromptDialog = null;
-        }
-
-        mWaitPromptDialog = new AlertDialog.Builder(this)
-                .setMessage(buf.toString())
-                .setPositiveButton(R.string.send_button, new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int whichButton) {
-                            if (DBG) log("handle WAIT_PROMPT_CONFIRMED, proceed...");
-                            c.proceedAfterWaitChar();
-                            PhoneApp.getInstance().pokeUserActivity();
-                        }
-                    })
-                .setOnCancelListener(new DialogInterface.OnCancelListener() {
-                        public void onCancel(DialogInterface dialog) {
-                            if (DBG) log("handle POST_DIAL_CANCELED!");
-                            c.cancelPostDial();
-                            PhoneApp.getInstance().pokeUserActivity();
-                        }
-                    })
-                .create();
-        mWaitPromptDialog.getWindow().addFlags(
-                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
-        mWaitPromptDialog.show();
-    }
-
     /**
-     * Processes the CDMA specific requirements of a WAIT character in a
-     * dial string.
-     *
      * Pop up an alert dialog with OK and Cancel buttons to allow user to
      * Accept or Reject the WAIT inserted as part of the Dial string.
      */
-    private void showWaitPromptDialogCDMA(final Connection c, String postDialStr) {
-        if (DBG) log("showWaitPromptDialogCDMA: '" + postDialStr + "'...");
+    private void showWaitPromptDialog(final Connection c, String postDialStr) {
+        if (DBG) log("showWaitPromptDialogChoice: '" + postDialStr + "'...");
 
         Resources r = getResources();
         StringBuilder buf = new StringBuilder();
@@ -2167,6 +2146,7 @@
                 .create();
         mWaitPromptDialog.getWindow().addFlags(
                 WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+
         mWaitPromptDialog.show();
     }
 
@@ -2174,7 +2154,7 @@
      * Pop up an alert dialog which waits for 2 seconds for each P (Pause) Character entered
      * as part of the Dial String.
      */
-    private void showPausePromptDialogCDMA(final Connection c, String postDialStrAfterPause) {
+    private void showPausePromptDialog(final Connection c, String postDialStrAfterPause) {
         Resources r = getResources();
         StringBuilder buf = new StringBuilder();
         buf.append(r.getText(R.string.pause_prompt_str));
@@ -2378,13 +2358,13 @@
                      && (fgLatestConnection.getPostDialState() == Connection.PostDialState.WAIT)) {
                     if(DBG) log("show the Wait dialog for CDMA");
                     postDialStr = fgLatestConnection.getRemainingPostDialString();
-                    showWaitPromptDialogCDMA(fgLatestConnection, postDialStr);
+                    showWaitPromptDialog(fgLatestConnection, postDialStr);
                 }
             } else if (phoneType == Phone.PHONE_TYPE_GSM) {
                 for (Connection cn : fgConnections) {
                     if ((cn != null) && (cn.getPostDialState() == Connection.PostDialState.WAIT)) {
                         postDialStr = cn.getRemainingPostDialString();
-                        showWaitPromptDialogGSM(cn, postDialStr);
+                        showWaitPromptDialog(cn, postDialStr);
                     }
                 }
             } else {
@@ -2413,27 +2393,33 @@
         // Make sure the Phone is "in use".  (If not, we shouldn't be on
         // this screen in the first place.)
 
-        // Need to treat running MMI codes as a connection as well.
-        // Do not check for getPendingMmiCodes when phone is a CDMA phone
-        int phoneType = mPhone.getPhoneType();
-
-        if ((phoneType == Phone.PHONE_TYPE_CDMA)
+        // An active or just-ended OTA call counts as "in use".
+        if (TelephonyCapabilities.supportsOtasp(mPhone)
                 && ((mInCallScreenMode == InCallScreenMode.OTA_NORMAL)
-                || (mInCallScreenMode == InCallScreenMode.OTA_ENDED))) {
+                    || (mInCallScreenMode == InCallScreenMode.OTA_ENDED))) {
             // Even when OTA Call ends, need to show OTA End UI,
             // so return Success to allow UI update.
             return InCallInitStatus.SUCCESS;
         }
 
-        if ((phoneType == Phone.PHONE_TYPE_CDMA)
-                || !mForegroundCall.isIdle() || !mBackgroundCall.isIdle() || !mRingingCall.isIdle()
-                || !mPhone.getPendingMmiCodes().isEmpty()) {
+        // If an MMI code is running that also counts as "in use".
+        //
+        // TODO: We currently only call getPendingMmiCodes() for GSM
+        //   phones.  (The code's been that way all along.)  But CDMAPhone
+        //   does in fact implement getPendingMmiCodes(), so should we
+        //   check that here regardless of the phone type?
+        boolean hasPendingMmiCodes =
+                (mPhone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+                && !mPhone.getPendingMmiCodes().isEmpty();
+
+        if (!mForegroundCall.isIdle() || !mBackgroundCall.isIdle() || !mRingingCall.isIdle()
+                || hasPendingMmiCodes) {
             if (VDBG) log("syncWithPhoneState: it's ok to be here; update the screen...");
             updateScreen();
             return InCallInitStatus.SUCCESS;
         }
 
-        if (DBG) log("syncWithPhoneState: phone is idle; we shouldn't be here!");
+        Log.i(LOG_TAG, "syncWithPhoneState: phone is idle (shouldn't be here)");
         return InCallInitStatus.PHONE_NOT_IN_USE;
     }
 
@@ -2552,7 +2538,7 @@
 
         final PhoneApp app = PhoneApp.getInstance();
 
-        if ((mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) && (mPhone.isOtaSpNumber(number))) {
+        if ((TelephonyCapabilities.supportsOtasp(mPhone)) && (mPhone.isOtaSpNumber(number))) {
             if (DBG) log("placeCall: isOtaSpNumber() returns true");
             setInCallScreenMode(InCallScreenMode.OTA_NORMAL);
             if (app.cdmaOtaProvisionData != null) {
@@ -2569,15 +2555,8 @@
         int callStatus;
         Uri contactUri = intent.getData();
 
-        if (null != mProviderGatewayUri &&
-            !(isEmergencyNumber || isEmergencyIntent) &&
-            PhoneUtils.isRoutableViaGateway(number)) {  // Filter out MMI, OTA and other codes.
-
-            callStatus = PhoneUtils.placeCallVia(
-                this, mPhone, number, contactUri, mProviderGatewayUri);
-        } else {
-            callStatus = PhoneUtils.placeCall(mPhone, number, contactUri);
-        }
+        callStatus = PhoneUtils.placeCall(this, mPhone, number, contactUri,
+                (isEmergencyNumber || isEmergencyIntent), mProviderGatewayUri);
 
         switch (callStatus) {
             case PhoneUtils.CALL_STATUS_DIALED:
@@ -3190,9 +3169,11 @@
                                                          mProviderAddress);
 
             TextView message = (TextView) findViewById(R.id.callingVia);
-            message.setCompoundDrawablesWithIntrinsicBounds(mProviderIcon, null, null, null);
             message.setText(text);
 
+            ImageView image = (ImageView) findViewById(R.id.callingViaIcon);
+            image.setImageDrawable(mProviderIcon);
+
             overlay.setVisibility(View.VISIBLE);
 
             // Remove any zombie messages and then send a message to
@@ -4682,7 +4663,7 @@
             return false;
         }
 
-        if (mPhone.getPhoneType() != Phone.PHONE_TYPE_CDMA) {
+        if (!TelephonyCapabilities.supportsOtasp(mPhone)) {
             return false;
         }
 
@@ -4765,7 +4746,7 @@
     private boolean initOtaState() {
         boolean inOtaCall = false;
 
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+        if (TelephonyCapabilities.supportsOtasp(mPhone)) {
             final PhoneApp app = PhoneApp.getInstance();
 
             if ((app.cdmaOtaScreenState == null) || (app.cdmaOtaProvisionData == null)) {
@@ -4803,7 +4784,7 @@
 
     public void updateMenuItems() {
         if (mInCallMenu != null) {
-            boolean okToShowMenu =  mInCallMenu.updateItems(PhoneApp.getInstance().phone);
+            boolean okToShowMenu =  mInCallMenu.updateItems(PhoneApp.getPhone());
             if (!okToShowMenu) {
                 dismissMenu(true);
             }
diff --git a/phone/src/com/android/phone2/InCallTouchUi.java b/phone/src/com/android/phone2/InCallTouchUi.java
index a568b65..edec37b 100644
--- a/phone/src/com/android/phone2/InCallTouchUi.java
+++ b/phone/src/com/android/phone2/InCallTouchUi.java
@@ -183,7 +183,7 @@
         mSwapButton = (ImageButton) mInCallControls.findViewById(R.id.swapButton);
         mSwapButton.setOnClickListener(this);
         mSwapButtonLabel = (TextView) mInCallControls.findViewById(R.id.swapButtonLabel);
-        if (PhoneApp.getInstance().phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+        if (PhoneApp.getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA) {
             // In CDMA we use a generalized text - "Manage call", as behavior on selecting
             // this option depends entirely on what the current call state is.
             mSwapButtonLabel.setText(R.string.onscreenManageCallsText);
diff --git a/phone/src/com/android/phone2/NetworkSetting.java b/phone/src/com/android/phone2/NetworkSetting.java
index 7fcf75f..df893ba 100644
--- a/phone/src/com/android/phone2/NetworkSetting.java
+++ b/phone/src/com/android/phone2/NetworkSetting.java
@@ -218,7 +218,7 @@
 
         addPreferencesFromResource(R.xml.carrier_select);
 
-        mPhone = PhoneApp.getInstance().phone;
+        mPhone = PhoneApp.getPhone();
 
         mNetworkList = (PreferenceGroup) getPreferenceScreen().findPreference(LIST_NETWORKS_KEY);
         mNetworkMap = new HashMap<Preference, NetworkInfo>();
diff --git a/phone/src/com/android/phone2/NotificationMgr.java b/phone/src/com/android/phone2/NotificationMgr.java
index d9f1972..2e7503a 100644
--- a/phone/src/com/android/phone2/NotificationMgr.java
+++ b/phone/src/com/android/phone2/NotificationMgr.java
@@ -84,8 +84,8 @@
     private StatusBarManager mStatusBar;
     private StatusBarMgr mStatusBarMgr;
     private Toast mToast;
-    private IBinder mSpeakerphoneIcon;
-    private IBinder mMuteIcon;
+    private boolean mShowingSpeakerphoneIcon;
+    private boolean mShowingMuteIcon;
 
     // used to track the missed call counter, default to 0.
     private int mNumberMissedCalls = 0;
@@ -433,16 +433,16 @@
     }
 
     void notifySpeakerphone() {
-        if (mSpeakerphoneIcon == null) {
-            mSpeakerphoneIcon = mStatusBar.addIcon("speakerphone",
-                    android.R.drawable.stat_sys_speakerphone, 0);
+        if (!mShowingSpeakerphoneIcon) {
+            mStatusBar.setIcon("speakerphone", android.R.drawable.stat_sys_speakerphone, 0);
+            mShowingSpeakerphoneIcon = true;
         }
     }
 
     void cancelSpeakerphone() {
-        if (mSpeakerphoneIcon != null) {
-            mStatusBar.removeIcon(mSpeakerphoneIcon);
-            mSpeakerphoneIcon = null;
+        if (mShowingSpeakerphoneIcon) {
+            mStatusBar.removeIcon("speakerphone");
+            mShowingSpeakerphoneIcon = false;
         }
     }
 
@@ -463,15 +463,16 @@
     }
 
     void notifyMute() {
-        if (mMuteIcon == null) {
-            mMuteIcon = mStatusBar.addIcon("mute", android.R.drawable.stat_notify_call_mute, 0);
+        if (mShowingMuteIcon) {
+            mStatusBar.setIcon("mute", android.R.drawable.stat_notify_call_mute, 0);
+            mShowingMuteIcon = true;
         }
     }
 
     void cancelMute() {
-        if (mMuteIcon != null) {
-            mStatusBar.removeIcon(mMuteIcon);
-            mMuteIcon = null;
+        if (mShowingMuteIcon) {
+            mStatusBar.removeIcon("mute");
+            mShowingMuteIcon = false;
         }
     }
 
@@ -502,9 +503,7 @@
 
         // Display the appropriate "in-call" icon in the status bar,
         // which depends on the current phone and/or bluetooth state.
-
-
-        boolean enhancedVoicePrivacy = PhoneApp.getInstance().notifier.getCdmaVoicePrivacyState();
+        boolean enhancedVoicePrivacy = PhoneApp.getInstance().notifier.getVoicePrivacyState();
         if (DBG) log("updateInCallNotification: enhancedVoicePrivacy = " + enhancedVoicePrivacy);
 
         if (!hasActiveCall && hasHoldingCall) {
@@ -749,7 +748,7 @@
                 }
             }
 
-            if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+            if (TelephonyCapabilities.supportsVoiceMessageCount(mPhone)) {
                 int vmCount = mPhone.getVoiceMessageCount();
                 String titleFormat = mContext.getString(R.string.notification_voicemail_title_count);
                 notificationTitle = String.format(titleFormat, vmCount);
@@ -815,7 +814,7 @@
             if (showExpandedNotification) {
                 Intent intent = new Intent(Intent.ACTION_MAIN);
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                intent.setClassName("com.android.phone",
+                intent.setClassName("com.android.phone2",
                         "com.android.phone2.CallFeaturesSetting");
 
                 notification = new Notification(
@@ -903,7 +902,7 @@
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
         // Use NetworkSetting to handle the selection intent
-        intent.setComponent(new ComponentName("com.android.phone",
+        intent.setComponent(new ComponentName("com.android.phone2",
                 "com.android.phone2.NetworkSetting"));
         PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
 
@@ -926,7 +925,7 @@
      * @param serviceState Phone service state
      */
     void updateNetworkSelection(int serviceState) {
-        if (mPhone.getPhoneType() == Phone.PHONE_TYPE_GSM) {
+        if (TelephonyCapabilities.supportsNetworkSelection(mPhone)) {
             // get the shared preference of network_selection.
             // empty is auto mode, otherwise it is the operator alpha name
             // in case there is no operator name, check the operator numeric
diff --git a/phone/src/com/android/phone2/OtaStartupReceiver.java b/phone/src/com/android/phone2/OtaStartupReceiver.java
index bd16435..d38976f 100644
--- a/phone/src/com/android/phone2/OtaStartupReceiver.java
+++ b/phone/src/com/android/phone2/OtaStartupReceiver.java
@@ -53,13 +53,13 @@
     public void onReceive(Context context, Intent intent) {
         mContext = context;
 
-        if (!OtaUtils.isCdmaPhone()) {
-            if (DBG) Log.d(TAG, "Not a CDMA phone, no need to process OTA");
+        if (!TelephonyCapabilities.supportsOtasp(PhoneApp.getPhone())) {
+            if (DBG) Log.d(TAG, "OTASP not supported, nothing to do.");
             return;
         }
 
         if (shouldPostpone(context)) {
-            if (DBG) Log.d(TAG, "Postponing CDMA provisioning until wizard runs");
+            if (DBG) Log.d(TAG, "Postponing OTASP until wizard runs");
             return;
         }
 
diff --git a/phone/src/com/android/phone2/OtaUtils.java b/phone/src/com/android/phone2/OtaUtils.java
index 1632cb9..5a4ebc1 100644
--- a/phone/src/com/android/phone2/OtaUtils.java
+++ b/phone/src/com/android/phone2/OtaUtils.java
@@ -48,6 +48,13 @@
 import android.widget.TextView;
 
 /**
+ * TODO: This is Over The Air Service Provisioning (OTASP)
+ *       A better name would be OtaspUtils.java.
+ *
+ * TODO: OTASP could UI may be substantially different on
+ *       future devices, and may not necessarily be built-in
+ *       to the InCallScreen.
+ *
  * Handles all OTA Call related logic and UI functionality.
  * The InCallScreen interacts with this class to perform an OTA Call.
  *
@@ -58,8 +65,6 @@
  */
 public class OtaUtils {
     private static final String LOG_TAG = "OtaUtils";
-    private static final String UNACTIVATED_MIN2_VALUE = "000000";
-    private static final String UNACTIVATED_MIN_VALUE = "1111110111";
     private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 1);
 
     public static final int OTA_SHOW_ACTIVATION_SCREEN_OFF = 0;
@@ -145,22 +150,6 @@
     }
 
     /**
-     * Returns true if the phone needs activation.
-     *
-     * @param minString the phone's MIN configuration string
-     * @return true if phone needs activation
-     * @throws OtaConfigurationException if the string is invalid
-     */
-    public static boolean needsActivation(String minString) throws IllegalArgumentException {
-        if (minString == null || (minString.length() < 6)) {
-            throw new IllegalArgumentException();
-        }
-        return (minString.equals(UNACTIVATED_MIN_VALUE)
-                || minString.substring(0,6).equals(UNACTIVATED_MIN2_VALUE))
-                || SystemProperties.getBoolean("test_cdma_setup", false);
-    }
-
-    /**
      * Starts the OTA provisioning call.  If the MIN isn't available yet, it returns false and adds
      * an event to return the request to the calling app when it becomes available.
      *
@@ -184,20 +173,9 @@
             phone.registerForSubscriptionInfoReady(handler, request, null);
             return false;
         }
-
         phone.unregisterForSubscriptionInfoReady(handler);
-        String min = phone.getCdmaMin();
 
-        if (DBG) log("min_string: " + min);
-
-        boolean phoneNeedsActivation = false;
-        try {
-            phoneNeedsActivation = needsActivation(min);
-        } catch (IllegalArgumentException e) {
-            if (DBG) log("invalid MIN string, exit");
-            return true; // If the MIN string is wrong, there's nothing else we can do.
-        }
-
+        boolean phoneNeedsActivation = phone.needsOtaServiceProvisioning();
         if (DBG) log("phoneNeedsActivation is set to " + phoneNeedsActivation);
 
         int otaShowActivationScreen = context.getResources().getInteger(
@@ -429,7 +407,7 @@
 
     /**
      * Show either programming success dialog when OTA provisioning succeeds, or
-     * programming failure dialog when it fails. See {@link otaShowProgramFailure}
+     * programming failure dialog when it fails. See {@link #otaShowProgramFailure}
      * for more details.
      */
     public void otaShowSuccessFailure() {
@@ -1013,7 +991,7 @@
         Log.d(LOG_TAG, msg);
     }
 
-    public static boolean isCdmaPhone() {
-        return (PhoneApp.getInstance().phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+    private static boolean isCdmaPhone() {
+        return (PhoneApp.getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA);
     }
 }
diff --git a/phone/src/com/android/phone2/OutgoingCallBroadcaster.java b/phone/src/com/android/phone2/OutgoingCallBroadcaster.java
index e7994af..2ad7e07 100644
--- a/phone/src/com/android/phone2/OutgoingCallBroadcaster.java
+++ b/phone/src/com/android/phone2/OutgoingCallBroadcaster.java
@@ -95,8 +95,8 @@
 
             number = getResultData();
             final PhoneApp app = PhoneApp.getInstance();
-            int phoneType = app.phone.getPhoneType();
-            if (phoneType == Phone.PHONE_TYPE_CDMA) {
+
+            if (TelephonyCapabilities.supportsOtasp(app.phone)) {
                 boolean activateState = (app.cdmaOtaScreenState.otaScreenState
                         == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION);
                 boolean dialogState = (app.cdmaOtaScreenState.otaScreenState
@@ -124,9 +124,9 @@
             if (number == null) {
                 if (DBG) Log.v(TAG, "CALL cancelled (null number), returning...");
                 return;
-            } else if ((phoneType == Phone.PHONE_TYPE_CDMA)
-                    && ((app.phone.getState() != Phone.State.IDLE)
-                    && (app.phone.isOtaSpNumber(number)))) {
+            } else if (TelephonyCapabilities.supportsOtasp(app.phone)
+                    && (app.phone.getState() != Phone.State.IDLE)
+                    && (app.phone.isOtaSpNumber(number))) {
                 if (DBG) Log.v(TAG, "Call is active, a 2nd OTA call cancelled -- returning.");
                 return;
             } else if (PhoneNumberUtils.isEmergencyNumber(number)) {
@@ -286,7 +286,7 @@
         if (number == null || TextUtils.isEmpty(number)) {
             if (intent.getBooleanExtra(EXTRA_SEND_EMPTY_FLASH, false)) {
                 Log.i(TAG, "onCreate: SEND_EMPTY_FLASH...");
-                PhoneUtils.sendEmptyFlash(PhoneApp.getInstance().phone);
+                PhoneUtils.sendEmptyFlash(PhoneApp.getPhone());
                 finish();
                 return;
             } else {
diff --git a/phone/src/com/android/phone2/PhoneApp.java b/phone/src/com/android/phone2/PhoneApp.java
index 0072f3a..936292d 100755
--- a/phone/src/com/android/phone2/PhoneApp.java
+++ b/phone/src/com/android/phone2/PhoneApp.java
@@ -387,6 +387,7 @@
     @Override
     public void onCreate() {
         if (VDBG) Log.v(LOG_TAG, "onCreate()...");
+        Log.v(LOG_TAG, "haha");
 
         ContentResolver resolver = getContentResolver();
 
@@ -458,9 +459,7 @@
             }
 
             // register for MMI/USSD
-            if (phoneType == Phone.PHONE_TYPE_GSM) {
-                phone.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
-            }
+            phone.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
 
             // register connection tracking to PhoneUtils
             PhoneUtils.initializeConnectionHandler(phone);
@@ -527,9 +526,7 @@
             }
         }
 
-        boolean phoneIsCdma = (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
-
-        if (phoneIsCdma) {
+        if (TelephonyCapabilities.supportsOtasp(phone)) {
             cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
             cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
             cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
@@ -588,6 +585,13 @@
         return sMe;
     }
 
+    /**
+     * Returns the Phone associated with this instance
+     */
+    static Phone getPhone() {
+        return getInstance().phone;
+    }
+
     Ringer getRinger() {
         return ringer;
     }
@@ -613,7 +617,7 @@
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                 | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
-        intent.setClassName("com.android.phone", getCallScreenClassName());
+        intent.setClassName("com.android.phone2", getCallScreenClassName());
         return intent;
     }
 
@@ -707,11 +711,12 @@
      */
     void dismissCallScreen() {
         if (mInCallScreen != null) {
-            if (mInCallScreen.isOtaCallInActiveState()
+            if ((TelephonyCapabilities.supportsOtasp(phone)) &&
+                    (mInCallScreen.isOtaCallInActiveState()
                     || mInCallScreen.isOtaCallInEndState()
                     || ((cdmaOtaScreenState != null)
                     && (cdmaOtaScreenState.otaScreenState
-                            != CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED))) {
+                            != CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED)))) {
                 // TODO: During OTA Call, display should not become dark to
                 // allow user to see OTA UI update. Phone app needs to hold
                 // a SCREEN_DIM_WAKE_LOCK wake lock during the entire OTA call.
@@ -1255,11 +1260,12 @@
     private void initForNewRadioTechnology() {
         if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
 
-        if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+         if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
             // Create an instance of CdmaPhoneCallState and initialize it to IDLE
             cdmaPhoneCallState = new CdmaPhoneCallState();
             cdmaPhoneCallState.CdmaPhoneCallStateInit();
-
+        }
+        if (TelephonyCapabilities.supportsOtasp(phone)) {
             //create instances of CDMA OTA data classes
             if (cdmaOtaProvisionData == null) {
                 cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
@@ -1273,6 +1279,9 @@
             if (cdmaOtaInCallScreenUiState == null) {
                 cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();
             }
+        } else {
+            //Clean up OTA data in GSM/UMTS. It is valid only for CDMA
+            clearOtaState();
         }
 
         ringer.updateRingerContextAfterRadioTechnologyChange(this.phone);
@@ -1459,7 +1468,7 @@
             } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
                 handleServiceStateChanged(intent);
             } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
-                if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+                if (TelephonyCapabilities.supportsEcm(phone)) {
                     Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
                     // Start Emergency Callback Mode service
                     if (intent.getBooleanExtra("phoneinECMState", false)) {
@@ -1467,8 +1476,10 @@
                                 EmergencyCallbackModeService.class));
                     }
                 } else {
-                    Log.e(LOG_TAG, "Error! Emergency Callback Mode not supported for " +
-                            phone.getPhoneName() + " phones");
+                    // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
+                    // on a device that doesn't support ECM in the first place.
+                    Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, "
+                          + "but ECM isn't supported for phone: " + phone.getPhoneName());
                 }
             } else if (action.equals(Intent.ACTION_DOCK_EVENT)) {
                 mDockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
@@ -1544,21 +1555,9 @@
         // If service just returned, start sending out the queued messages
         ServiceState ss = ServiceState.newFromBundle(intent.getExtras());
 
-        boolean hasService = true;
-        boolean isCdma = false;
-        String eriText = "";
-
         if (ss != null) {
             int state = ss.getState();
             NotificationMgr.getDefault().updateNetworkSelection(state);
-            switch (state) {
-                case ServiceState.STATE_OUT_OF_SERVICE:
-                case ServiceState.STATE_POWER_OFF:
-                    hasService = false;
-                    break;
-            }
-        } else {
-            hasService = false;
         }
     }
 
diff --git a/phone/src/com/android/phone2/PhoneInterfaceManager.java b/phone/src/com/android/phone2/PhoneInterfaceManager.java
index e42f95b..f46ae52 100644
--- a/phone/src/com/android/phone2/PhoneInterfaceManager.java
+++ b/phone/src/com/android/phone2/PhoneInterfaceManager.java
@@ -135,18 +135,7 @@
 
                 case CMD_END_CALL:
                     request = (MainThreadRequest) msg.obj;
-                    boolean hungUp = false;
-                    int phoneType = mPhone.getPhoneType();
-                    if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                        // CDMA: If the user presses the Power button we treat it as
-                        // ending the complete call session
-                        hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
-                    } else if (phoneType == Phone.PHONE_TYPE_GSM) {
-                        // GSM: End the call as per the Phone state
-                        hungUp = PhoneUtils.hangup(mPhone);
-                    } else {
-                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
-                    }
+                    boolean hungUp = PhoneUtils.hangup(mPhone);
                     if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
                     request.result = hungUp;
                     // Wake up the requesting thread
@@ -209,7 +198,7 @@
     private void publish() {
         if (DBG) log("publish: " + this);
 
-        //ServiceManager.addService("phone", this);
+        ServiceManager.addService("phone", this);
     }
 
     //
@@ -665,20 +654,8 @@
     /**
      * Returns true if CDMA provisioning needs to run.
      */
-    public boolean getCdmaNeedsProvisioning() {
-        if (getActivePhoneType() == Phone.PHONE_TYPE_GSM) {
-            return false;
-        }
-
-        boolean needsProvisioning = false;
-        String cdmaMin = mPhone.getCdmaMin();
-        try {
-            needsProvisioning = OtaUtils.needsActivation(cdmaMin);
-        } catch (IllegalArgumentException e) {
-            // shouldn't get here unless hardware is misconfigured
-            Log.e(LOG_TAG, "CDMA MIN string " + ((cdmaMin == null) ? "was null" : "was too short"));
-        }
-        return needsProvisioning;
+    public boolean needsOtaServiceProvisioning() {
+        return mPhone.needsOtaServiceProvisioning();
     }
 
     /**
@@ -715,6 +692,8 @@
                 return TelephonyManager.NETWORK_TYPE_EVDO_0;
             case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
                 return TelephonyManager.NETWORK_TYPE_EVDO_A;
+            case ServiceState.RADIO_TECHNOLOGY_EVDO_B:
+                return TelephonyManager.NETWORK_TYPE_EVDO_B;
             default:
                 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
         }
diff --git a/phone/src/com/android/phone2/PhoneUtils.java b/phone/src/com/android/phone2/PhoneUtils.java
index d7e9e73..b064226 100755
--- a/phone/src/com/android/phone2/PhoneUtils.java
+++ b/phone/src/com/android/phone2/PhoneUtils.java
@@ -276,11 +276,10 @@
                 //if (DBG) log("sPhone.acceptCall");
                 phone.acceptCall();
                 answered = true;
-                if (phoneIsCdma) {
-                    // automatically reset mute state to unmuted for CDMA
-                    // TODO: Would GSM want this also?
-                    setMute(phone, false);
-                }
+
+                // Always reset to "unmuted" for a freshly-answered call
+                setMute(phone, false);
+
                 setAudioMode(phone.getContext(), AudioManager.MODE_IN_CALL);
 
                 // Check is phone in any dock, and turn on speaker accordingly
@@ -336,37 +335,43 @@
     }
 
     static boolean hangupRingingCall(Phone phone) {
-        if (DBG) log("hangup ringing call");
+        if (DBG) log("hangupRingingCall()...");
         Call ringing = phone.getRingingCall();
-        int phoneType = phone.getPhoneType();
+        Call.State state = ringing.getState();
 
-        if (phoneType == Phone.PHONE_TYPE_CDMA) {
-            // CDMA: Ringing call and Call waiting hangup is handled differently.
-            // For Call waiting we DO NOT call the conventional hangup(call) function
-            // as in CDMA we just want to hungup the Call waiting connection.
-            Call.State state = ringing.getState();
-            if (state == Call.State.INCOMING) {
-                if (DBG) log("hangup ringing call");
-                return hangup(ringing);
-            } else if (state == Call.State.WAITING) {
-                if (DBG) log("hangup Call waiting call");
+        if (state == Call.State.INCOMING) {
+            // Regular incoming call (with no other active calls)
+            if (DBG) log("- regular incoming call: hangup()");
+            return hangup(ringing);
+        } else if (state == Call.State.WAITING) {
+            // Call-waiting: there's an incoming call, but another call is
+            // already active.
+            // TODO: It would be better for the telephony layer to provide
+            // a "hangupWaitingCall()" API that works on all devices,
+            // rather than us having to check the phone type here and do
+            // the notifier.sendCdmaCallWaitingReject() hack for CDMA phones.
+            if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+                // CDMA: Ringing call and Call waiting hangup is handled differently.
+                // For Call waiting we DO NOT call the conventional hangup(call) function
+                // as in CDMA we just want to hangup the Call waiting connection.
+                if (DBG) log("- CDMA-specific call-waiting hangup");
                 final CallNotifier notifier = PhoneApp.getInstance().notifier;
                 notifier.sendCdmaCallWaitingReject();
                 return true;
             } else {
-                // This should never happen cause hangupRingingCall should always be called
-                // if the call.isRinging() returns TRUE, which basically means that the call
-                // should either be in INCOMING or WAITING state
-                if (DBG) log("No Ringing call to hangup");
-                return false;
+                // Otherwise, the regular hangup() API works for
+                // call-waiting calls too.
+                if (DBG) log("- call-waiting call: hangup()");
+                return hangup(ringing);
             }
-        } else if (phoneType == Phone.PHONE_TYPE_GSM) {
-            // GSM:  Ringing Call and Call waiting, both are hungup by calling
-            // hangup(call) function.
-            if (DBG) log("hangup ringing call");
-            return hangup(ringing);
         } else {
-            throw new IllegalStateException("Unexpected phone type: " + phoneType);
+            // Unexpected state: the ringing call isn't INCOMING or
+            // WAITING, so there's no reason to have called
+            // hangupRingingCall() in the first place.
+            // (Presumably the incoming call went away at the exact moment
+            // we got here, so just do nothing.)
+            Log.w(LOG_TAG, "hangupRingingCall: no INCOMING or WAITING call");
+            return false;
         }
     }
 
@@ -492,173 +497,149 @@
     /**
      * Dial the number using the phone passed in.
      *
-     * @param phone the Phone object.
-     * @param number to be dialed as requested by the user.
-     * @param contactRef that triggered the call. Either a 'tel:' or a
-     * 'content://contacts' uri depending on how the call was
-     * initiated (dialpad vs contact).
-     * @return either CALL_STATUS_DIALED, CALL_STATUS_DIALED_MMI, or CALL_STATUS_FAILED
-     */
-    static int placeCall(Phone phone, String number, Uri contactRef) {
-        int status = CALL_STATUS_DIALED;
-        try {
-            if (DBG) log("placeCall: '" + number + "'...");
-
-            Connection cn = phone.dial(number);
-            if (DBG) log("===> phone.dial() returned: " + cn);
-
-            int phoneType = phone.getPhoneType();
-
-            // On GSM phones, null is returned for MMI codes
-            if (cn == null) {
-                if (phoneType == Phone.PHONE_TYPE_GSM) {
-                    if (DBG) log("dialed MMI code: " + number);
-                    status = CALL_STATUS_DIALED_MMI;
-                    // Set dialed MMI command to service
-                    if (mNwService != null) {
-                        try {
-                            mNwService.setMmiString(number);
-                            if (DBG) log("Extended NW bindService setUssdString (" + number + ")");
-                        } catch (RemoteException e) {
-                            mNwService = null;
-                        }
-                    }
-                } else {
-                    status = PhoneUtils.CALL_STATUS_FAILED;
-                }
-            } else {
-                PhoneApp app = PhoneApp.getInstance();
-
-                if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                    updateCdmaCallStateOnNewOutgoingCall(app);
-                }
-
-                PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_OFFHOOK);
-
-                // phone.dial() succeeded: we're now in a normal phone call.
-                // attach the URI to the CallerInfo Object if it is there,
-                // otherwise just attach the Uri Reference.
-                // if the uri does not have a "content" scheme, then we treat
-                // it as if it does NOT have a unique reference.
-                String content = phone.getContext().getContentResolver().SCHEME_CONTENT;
-                if ((contactRef != null) && (contactRef.getScheme().equals(content))) {
-                    Object userDataObject = cn.getUserData();
-                    if (userDataObject == null) {
-                        cn.setUserData(contactRef);
-                    } else {
-                        // TODO: This branch is dead code, we have
-                        // just created the connection 'cn' which has
-                        // no user data (null) by default.
-                        if (userDataObject instanceof CallerInfo) {
-                            ((CallerInfo) userDataObject).contactRefUri = contactRef;
-                        } else {
-                            ((CallerInfoToken) userDataObject).currentInfo.contactRefUri =
-                                contactRef;
-                        }
-                    }
-                }
-                setAudioMode(phone.getContext(), AudioManager.MODE_IN_CALL);
-
-                // Check is phone in any dock, and turn on speaker accordingly
-                activateSpeakerIfDocked(phone);
-            }
-        } catch (CallStateException ex) {
-            Log.w(LOG_TAG, "Exception from phone.dial()", ex);
-            status = CALL_STATUS_FAILED;
-        }
-
-        return status;
-    }
-
-    /**
-     * Dial the number using a 3rd party provider gateway.  Should
-     * *NOT* be called if the number is either:
-     * . An emergency one
-     * . A GSM MMI code
-     * . A CDMA feature code
-     * None of the above is  checked in this method, it's the caller's
-     * responsability to make sure the number is 'valid'.
-     *
      * If the connection is establised, this method issues a sync call
      * that may block to query the caller info.
      * TODO: Change the logic to use the async query.
      *
-     * @param phone the Phone object.
      * @param context To perform the CallerInfo query.
+     * @param phone the Phone object.
      * @param number to be dialed as requested by the user. This is
      * NOT the phone number to connect to. It is used only to build the
      * call card and to update the call log. See above for restrictions.
      * @param contactRef that triggered the call. Typically a 'tel:'
      * uri but can also be a 'content://contacts' one.
-     * @param gatewayUri Is the address used to setup the connection.
+     * @param isEmergencyCall indicates that whether or not this is an
+     * emergency call
+     * @param gatewayUri Is the address used to setup the connection, null
+     * if not using a gateway
+     *
      * @return either CALL_STATUS_DIALED or CALL_STATUS_FAILED
      */
-    static int placeCallVia(Context context, Phone phone,
-                            String number, Uri contactRef, Uri gatewayUri) {
-        if (DBG) log("placeCallVia: '" + number + "' GW:'" + gatewayUri + "'");
-
-        // TODO: 'tel' should be a contant defined in framework base
-        // somewhere (it is in webkit.)
-        if (null == gatewayUri || !"tel".equals(gatewayUri.getScheme())) {
-            Log.e(LOG_TAG, "Unsupported URL:" + gatewayUri);
-            return CALL_STATUS_FAILED;
+    public static int placeCall(Context context, Phone phone,
+            String number, Uri contactRef, boolean isEmergencyCall, 
+            Uri gatewayUri) {
+        if (DBG) log("placeCall '" + number + "' GW:'" + gatewayUri + "'");
+        boolean useGateway = false;
+        if (null != gatewayUri &&
+            !isEmergencyCall &&
+            PhoneUtils.isRoutableViaGateway(number)) {  // Filter out MMI, OTA and other codes.
+            useGateway = true;
         }
 
-        // We can use getSchemeSpecificPart because we don't allow #
-        // in the gateway numbers (treated a fragment delim.) However
-        // if we allow more complex gateway numbers sequence (with
-        // passwords or whatnot) that use #, this may break.
-        // TODO: Need to support MMI codes.
-        String gatewayNumber = gatewayUri.getSchemeSpecificPart();
+        int status = CALL_STATUS_DIALED;
         Connection connection;
+        String numberToDial;
+        if (useGateway) {
+            // TODO: 'tel' should be a constant defined in framework base
+            // somewhere (it is in webkit.)
+            if (null == gatewayUri || !"tel".equals(gatewayUri.getScheme())) {
+                Log.e(LOG_TAG, "Unsupported URL:" + gatewayUri);
+                return CALL_STATUS_FAILED;
+            }
+
+            // We can use getSchemeSpecificPart because we don't allow #
+            // in the gateway numbers (treated a fragment delim.) However
+            // if we allow more complex gateway numbers sequence (with
+            // passwords or whatnot) that use #, this may break.
+            // TODO: Need to support MMI codes.
+            numberToDial = gatewayUri.getSchemeSpecificPart();
+        } else {
+            numberToDial = number;
+        }
+
         try {
-            connection = phone.dial(gatewayNumber);
+            connection = phone.dial(numberToDial);
         } catch (CallStateException ex) {
-            Log.e(LOG_TAG, "Exception dialing gateway", ex);
+            Log.e(LOG_TAG, "Exception dialing ", ex);
             connection = null;
         }
 
+        int phoneType = phone.getPhoneType();
+
+        // On GSM phones, null is returned for MMI codes
         if (null == connection) {
-            Log.e(LOG_TAG, "Got null connection.");
-            return CALL_STATUS_FAILED;
+            if (phoneType == Phone.PHONE_TYPE_GSM && gatewayUri == null) {
+                if (DBG) log("dialed MMI code: " + number);
+                status = CALL_STATUS_DIALED_MMI;
+                // Set dialed MMI command to service
+                if (mNwService != null) {
+                    try {
+                        mNwService.setMmiString(number);
+                        if (DBG) log("Extended NW bindService setUssdString (" + number + ")");
+                    } catch (RemoteException e) {
+                        mNwService = null;
+                    }
+                }
+            } else {
+                status = CALL_STATUS_FAILED;
+            }
+        } else {
+            PhoneApp app = PhoneApp.getInstance();
+            if (phoneType == Phone.PHONE_TYPE_CDMA) {
+                updateCdmaCallStateOnNewOutgoingCall(app);
+            }
+
+            PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_OFFHOOK);
+
+            // Clean up the number to be displayed.
+            if (phoneType == Phone.PHONE_TYPE_CDMA) {
+                number = CdmaConnection.formatDialString(number);
+            }
+            number = PhoneNumberUtils.extractNetworkPortion(number);
+            number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
+            number = PhoneNumberUtils.formatNumber(number);
+
+            if (gatewayUri == null) {
+                // phone.dial() succeeded: we're now in a normal phone call.
+                // attach the URI to the CallerInfo Object if it is there,
+                // otherwise just attach the Uri Reference.
+                // if the uri does not have a "content" scheme, then we treat
+                // it as if it does NOT have a unique reference.
+                String content = context.getContentResolver().SCHEME_CONTENT;
+                if ((contactRef != null) && (contactRef.getScheme().equals(content))) {
+                    Object userDataObject = connection.getUserData();
+                    if (userDataObject == null) {
+                        connection.setUserData(contactRef);
+                    } else {
+                        // TODO: This branch is dead code, we have
+                        // just created the connection which has
+                        // no user data (null) by default.
+                        if (userDataObject instanceof CallerInfo) {
+                        ((CallerInfo) userDataObject).contactRefUri = contactRef;
+                        } else {
+                        ((CallerInfoToken) userDataObject).currentInfo.contactRefUri =
+                            contactRef;
+                        }
+                    }
+                }
+            } else {
+                // Get the caller info synchronously because we need the final
+                // CallerInfo object to update the dialed number with the one
+                // requested by the user (and not the provider's gateway number).
+                CallerInfo info = null;
+                String content = phone.getContext().getContentResolver().SCHEME_CONTENT;
+                if ((contactRef != null) && (contactRef.getScheme().equals(content))) {
+                    info = CallerInfo.getCallerInfo(context, contactRef);
+                }
+
+                // Fallback, lookup contact using the phone number if the
+                // contact's URI scheme was not content:// or if is was but
+                // the lookup failed.
+                if (null == info) {
+                    info = CallerInfo.getCallerInfo(context, number);
+                }
+                info.phoneNumber = number;
+                connection.setUserData(info);
+            }
+
+            setAudioMode(phone.getContext(), AudioManager.MODE_IN_CALL);
+
+            if (DBG) log("about to activate speaker");
+            // Check is phone in any dock, and turn on speaker accordingly
+            activateSpeakerIfDocked(phone);
         }
 
-        PhoneApp app = PhoneApp.getInstance();
-        boolean phoneIsCdma = (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
-
-        if (phoneIsCdma) {
-            updateCdmaCallStateOnNewOutgoingCall(app);
-        }
-        PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_OFFHOOK);
-
-        // Clean up the number to be displayed.
-        if (phoneIsCdma) {
-            number = CdmaConnection.formatDialString(number);
-        }
-        number = PhoneNumberUtils.extractNetworkPortion(number);
-        number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
-        number = PhoneNumberUtils.formatNumber(number);
-
-        // Get the caller info synchronously because we need the final
-        // CallerInfo object to update the dialed number with the one
-        // requested by the user (and not the provider's gateway number).
-        CallerInfo info = null;
-
-        if (ContentResolver.SCHEME_CONTENT.equals(contactRef.getScheme())) {
-            info = CallerInfo.getCallerInfo(context, contactRef);
-        }
-
-        // Fallback, lookup contact using the phone number if the
-        // contact's URI scheme was not content:// or if is was but
-        // the lookup failed.
-        if (null == info) {
-            info = CallerInfo.getCallerInfo(context, number);
-        }
-        info.phoneNumber = number;
-        connection.setUserData(info);
-
-        setAudioMode(phone.getContext(), AudioManager.MODE_IN_CALL);
-        return CALL_STATUS_DIALED;
+        return status;
     }
 
     /**
@@ -1025,10 +1006,10 @@
                     new DialogInterface.OnClickListener() {
                         public void onClick(DialogInterface dialog, int whichButton) {
                             switch (whichButton) {
-                                case DialogInterface.BUTTON1:
+                                case DialogInterface.BUTTON_POSITIVE:
                                     phone.sendUssdResponse(inputText.getText().toString());
                                     break;
-                                case DialogInterface.BUTTON2:
+                                case DialogInterface.BUTTON_NEGATIVE:
                                     if (mmiCode.isCancelable()) {
                                         mmiCode.cancel();
                                     }
@@ -2297,19 +2278,21 @@
 
     /**
      * Returns whether the phone is in ECM ("Emergency Callback Mode") or not.
-     * (For non-CDMA phones, this will always return false.
-     * For CDMA Phones, return true iff PROPERTY_INECM_MODE == "true".)
      */
     /* package */ static boolean isPhoneInEcm(Phone phone) {
-        boolean phoneInEcm = false;
-        if ((phone != null) && (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA)) {
+        if ((phone != null) && TelephonyCapabilities.supportsEcm(phone)) {
+            // For phones that support ECM, return true iff PROPERTY_INECM_MODE == "true".
+            // TODO: There ought to be a better API for this than just
+            // exposing a system property all the way up to the app layer,
+            // probably a method like "inEcm()" provided by the telephony
+            // layer.
             String ecmMode =
                     SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);
             if (ecmMode != null) {
-                phoneInEcm = ecmMode.equals("true");
+                return ecmMode.equals("true");
             }
         }
-        return phoneInEcm;
+        return false;
     }
 
 
diff --git a/phone/src/com/android/phone2/Settings.java b/phone/src/com/android/phone2/Settings.java
index bf2b956..50e4d0a 100644
--- a/phone/src/com/android/phone2/Settings.java
+++ b/phone/src/com/android/phone2/Settings.java
@@ -35,7 +35,6 @@
 import android.util.Log;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 
@@ -48,17 +47,13 @@
     // debug data
     private static final String LOG_TAG = "NetworkSettings";
     private static final boolean DBG = true;
-    public static final int REQUEST_CODE_EXIT_ECM         = 17;
+    public static final int REQUEST_CODE_EXIT_ECM = 17;
 
     //String keys for preference lookup
     private static final String BUTTON_DATA_ENABLED_KEY = "button_data_enabled_key";
     private static final String BUTTON_DATA_USAGE_KEY = "button_data_usage_key";
     private static final String BUTTON_PREFERED_NETWORK_MODE = "preferred_network_mode_key";
     private static final String BUTTON_ROAMING_KEY = "button_roaming_key";
-    private static final String BUTTON_CDMA_ROAMING_KEY = "cdma_roaming_mode_key";
-
-    private static final String BUTTON_GSM_UMTS_OPTIONS = "gsm_umts_options_key";
-    private static final String BUTTON_CDMA_OPTIONS = "cdma_options_key";
 
     static final int preferredNetworkMode = Phone.PREFERRED_NT_MODE;
 
@@ -66,7 +61,6 @@
     private ListPreference mButtonPreferredNetworkMode;
     private CheckBoxPreference mButtonDataRoam;
     private CheckBoxPreference mButtonDataEnabled;
-    private CdmaRoamingListPreference mButtonCdmaRoam;
 
     private Preference mButtonDataUsage;
     private DataUsageListener mDataUsageListener;
@@ -77,14 +71,16 @@
     private boolean mOkClicked;
 
     //GsmUmts options and Cdma options
-    GsmUmtsOptions gsmumtsOptions;
-    CdmaOptions cdmaOptions;
+    GsmUmtsOptions mGsmUmtsOptions;
+    CdmaOptions mCdmaOptions;
+
+    private Preference mClickedPreference;
 
 
     //This is a method implemented for DialogInterface.OnClickListener.
     //  Used to dismiss the dialogs when they come up.
     public void onClick(DialogInterface dialog, int which) {
-        if (which == DialogInterface.BUTTON1) {
+        if (which == DialogInterface.BUTTON_POSITIVE) {
             mPhone.setDataRoamingEnabled(true);
             mOkClicked = true;
         } else {
@@ -107,13 +103,17 @@
      */
     @Override
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
-        if (gsmumtsOptions != null &&
-                gsmumtsOptions.onPreferenceTreeClick(preferenceScreen, preference) == true) {
+        /** TODO: Refactor and get rid of the if's using subclasses */
+        if (mGsmUmtsOptions != null &&
+                mGsmUmtsOptions.preferenceTreeClick(preference) == true) {
             return true;
-        } else if (cdmaOptions != null &&
-                   cdmaOptions.onPreferenceTreeClick(preferenceScreen, preference) == true) {
+        } else if (mCdmaOptions != null &&
+                   mCdmaOptions.preferenceTreeClick(preference) == true) {
             if (Boolean.parseBoolean(
                     SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
+
+                mClickedPreference = preference;
+
                 // In ECM mode launch ECM app dialog
                 startActivityForResult(
                     new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
@@ -127,8 +127,7 @@
                     preferredNetworkMode);
             mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
             return true;
-        }
-        else if (preference == mButtonDataRoam) {
+        } else if (preference == mButtonDataRoam) {
             if (DBG) log("onPreferenceTreeClick: preference == mButtonDataRoam.");
 
             //normally called on the toggle click
@@ -143,8 +142,7 @@
                         .setNegativeButton(android.R.string.no, this)
                         .show()
                         .setOnDismissListener(this);
-            }
-            else {
+            } else {
                 mPhone.setDataRoamingEnabled(false);
             }
             return true;
@@ -171,7 +169,7 @@
 
         addPreferencesFromResource(R.xml.network_setting);
 
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         mHandler = new MyHandler();
 
         //get UI object references
@@ -193,22 +191,15 @@
                     getContentResolver(),android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
                     preferredNetworkMode);
             mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode));
-            // The intent code that resided here in the past has been moved into the
-            // more conventional location in network_setting.xml
-
+            mCdmaOptions = new CdmaOptions(this, prefSet);
+            mGsmUmtsOptions = new GsmUmtsOptions(this, prefSet);
         } else {
             prefSet.removePreference(mButtonPreferredNetworkMode);
-            prefSet.removePreference(prefSet.findPreference(BUTTON_GSM_UMTS_OPTIONS));
-            prefSet.removePreference(prefSet.findPreference(BUTTON_CDMA_OPTIONS));
             int phoneType = mPhone.getPhoneType();
             if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                addPreferencesFromResource(R.xml.cdma_options);
-                mButtonCdmaRoam =
-                    (CdmaRoamingListPreference) prefSet.findPreference(BUTTON_CDMA_ROAMING_KEY);
-                cdmaOptions = new CdmaOptions();
+                mCdmaOptions = new CdmaOptions(this, prefSet);
             } else if (phoneType == Phone.PHONE_TYPE_GSM) {
-                addPreferencesFromResource(R.xml.gsm_umts_options);
-                gsmumtsOptions = new GsmUmtsOptions();
+                mGsmUmtsOptions = new GsmUmtsOptions(this, prefSet);
             } else {
                 throw new IllegalStateException("Unexpected phone type: " + phoneType);
             }
@@ -457,8 +448,8 @@
             Boolean isChoiceYes =
                 data.getBooleanExtra(EmergencyCallbackModeExitDialog.EXTRA_EXIT_ECM_RESULT, false);
             if (isChoiceYes) {
-                // If the phone exits from ECM mode, show the system selection Options
-                mButtonCdmaRoam.showDialog(null);
+                // If the phone exits from ECM mode, show the CDMA Options
+                mCdmaOptions.showDialog(mClickedPreference);
             } else {
                 // do nothing
             }
diff --git a/phone/src/com/android/phone2/SimContacts.java b/phone/src/com/android/phone2/SimContacts.java
index fa15fa3..7f9cb5e 100644
--- a/phone/src/com/android/phone2/SimContacts.java
+++ b/phone/src/com/android/phone2/SimContacts.java
@@ -130,11 +130,6 @@
         }
     }
 
-    // From HardCodedSources.java in Contacts app.
-    // TODO: fix this.
-    private static final String ACCOUNT_TYPE_GOOGLE = "com.google";
-    private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
-
     private static void actuallyImportOneSimContact(
             final Cursor cursor, final ContentResolver resolver, Account account) {
         final NamePhoneTypePair namePhoneTypePair =
@@ -158,23 +153,6 @@
         if (account != null) {
             builder.withValue(RawContacts.ACCOUNT_NAME, account.name);
             builder.withValue(RawContacts.ACCOUNT_TYPE, account.type);
-
-            // TODO: temporal fix for "My Groups" issue. Need to be refactored.
-            if (ACCOUNT_TYPE_GOOGLE.equals(account.type)) {
-                final Cursor tmpCursor = resolver.query(Groups.CONTENT_URI, new String[] {
-                        Groups.SOURCE_ID },
-                        Groups.TITLE + "=?", new String[] {
-                        GOOGLE_MY_CONTACTS_GROUP }, null);
-                try {
-                    if (tmpCursor != null && tmpCursor.moveToFirst()) {
-                        myGroupsId = tmpCursor.getString(0);
-                    }
-                } finally {
-                    if (tmpCursor != null) {
-                        tmpCursor.close();
-                    }
-                }
-            }
         } else {
             builder.withValues(sEmptyContentValues);
         }
@@ -291,6 +269,11 @@
 
                 ImportAllSimContactsThread thread = new ImportAllSimContactsThread();
 
+                // TODO: need to show some error dialog.
+                if (mCursor == null) {
+                    Log.e(LOG_TAG, "cursor is null. Ignore silently.");
+                    break;
+                }
                 mProgressDialog = new ProgressDialog(this);
                 mProgressDialog.setTitle(title);
                 mProgressDialog.setMessage(message);
@@ -298,9 +281,7 @@
                 mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
                         getString(R.string.cancel), thread);
                 mProgressDialog.setProgress(0);
-                if (mCursor != null) {
-                    mProgressDialog.setMax(mCursor.getCount());
-                }
+                mProgressDialog.setMax(mCursor.getCount());
                 mProgressDialog.show();
 
                 thread.start();
diff --git a/phone/src/com/android/phone2/SpecialCharSequenceMgr.java b/phone/src/com/android/phone2/SpecialCharSequenceMgr.java
index 3a80bc1..db31bbb 100644
--- a/phone/src/com/android/phone2/SpecialCharSequenceMgr.java
+++ b/phone/src/com/android/phone2/SpecialCharSequenceMgr.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.provider.Telephony.Intents;
-import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.Phone;
 import android.telephony.PhoneNumberUtils;
 import android.util.Log;
@@ -161,7 +160,7 @@
                 int index = Integer.parseInt(input.substring(0, len-1));
                 Intent intent = new Intent(Intent.ACTION_PICK);
 
-                intent.setClassName("com.android.phone",
+                intent.setClassName("com.android.phone2",
                                     "com.android.phone2.SimContacts");
                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 intent.putExtra("index", index);
@@ -199,43 +198,23 @@
     static private boolean handleIMEIDisplay(Context context,
                                              String input) {
         if (input.equals(MMI_IMEI_DISPLAY)) {
-            int phoneType = PhoneApp.getInstance().phone.getPhoneType();
-            if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                showMEIDPanel(context);
-                return true;
-            } else if (phoneType == Phone.PHONE_TYPE_GSM) {
-                showIMEIPanel(context);
-                return true;
-            }
+            showDeviceIdPanel(context);
+            return true;
         }
 
         return false;
     }
 
-    // TODO: showIMEIPanel and showMEIDPanel are almost cut and paste
-    // clones. Refactor.
-    static private void showIMEIPanel(Context context) {
-        if (DBG) log("showIMEIPanel");
+    static private void showDeviceIdPanel(Context context) {
+        if (DBG) log("showDeviceIdPanel()...");
 
-        String imeiStr = PhoneFactory.getDefaultPhone().getDeviceId();
+        Phone phone = PhoneApp.getPhone();
+        int labelId = TelephonyCapabilities.getDeviceIdLabel(phone);
+        String deviceId = phone.getDeviceId();
 
         AlertDialog alert = new AlertDialog.Builder(context)
-                .setTitle(R.string.imei)
-                .setMessage(imeiStr)
-                .setPositiveButton(R.string.ok, null)
-                .setCancelable(false)
-                .show();
-        alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PRIORITY_PHONE);
-    }
-
-    static private void showMEIDPanel(Context context) {
-        if (DBG) log("showMEIDPanel");
-
-        String meidStr = PhoneFactory.getDefaultPhone().getDeviceId();
-
-        AlertDialog alert = new AlertDialog.Builder(context)
-                .setTitle(R.string.meid)
-                .setMessage(meidStr)
+                .setTitle(labelId)
+                .setMessage(deviceId)
                 .setPositiveButton(R.string.ok, null)
                 .setCancelable(false)
                 .show();
diff --git a/phone/src/com/android/phone2/TelephonyCapabilities.java b/phone/src/com/android/phone2/TelephonyCapabilities.java
new file mode 100644
index 0000000..527b813
--- /dev/null
+++ b/phone/src/com/android/phone2/TelephonyCapabilities.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone2;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+
+/**
+ * TODO: This is intended as a temporary repository for behavior policy
+ * functions that depend upon the type of phone or the carrier.  Ultimately
+ * these sorts of questions should be answered by the telephony layer.
+ */
+public class TelephonyCapabilities {
+    private static final String LOG_TAG = "TelephonyCapabilities";
+
+    /** This class is never instantiated. */
+    private TelephonyCapabilities() {
+    }
+
+    /**
+     * On GSM devices, we never use short tones.
+     * On CDMA devices, it depends upon the settings.
+     * TODO: I don't think this has anything to do with GSM versus CDMA,
+     * should we be looking only at the setting?
+     */
+    /* package */ static boolean useShortDtmfTones(Phone phone, Context context) {
+        int phoneType = phone.getPhoneType();
+        if (phoneType == Phone.PHONE_TYPE_GSM) {
+            return false;
+        } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
+            int toneType = android.provider.Settings.System.getInt(
+                    context.getContentResolver(),
+                Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
+                CallFeaturesSetting.DTMF_TONE_TYPE_NORMAL);
+            if (toneType == CallFeaturesSetting.DTMF_TONE_TYPE_NORMAL) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            throw new IllegalStateException("Unexpected phone type: " + phoneType);
+        }
+    }
+
+    /**
+     * Return true if the current phone supports ECM ("Emergency Callback
+     * Mode"), which is a feature where the device goes into a special
+     * state for a short period of time after making an outgoing emergency
+     * call.
+     *
+     * (On current devices, that state lasts 5 minutes.  It prevents data
+     * usage by other apps, to avoid conflicts with any possible incoming
+     * calls.  It also puts up a notification in the status bar, showing a
+     * countdown while ECM is active, and allowing the user to exit ECM.)
+     *
+     * Currently this is assumed to be true for CDMA phones, and false
+     * otherwise.
+     *
+     * TODO: This capability should really be exposed by the telephony
+     * layer, since it depends on the underlying telephony technology.
+     * (Or, is this actually carrier-specific?  Is it VZW-only?)
+     */
+    /* package */ static boolean supportsEcm(Phone phone) {
+        return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+    }
+
+    /**
+     * Return true if the current phone supports Over The Air Service
+     * Provisioning (OTASP)
+     *
+     * Currently this is assumed to be true for CDMA phones, and false
+     * otherwise.
+     *
+     * TODO: This capability should really be exposed by the telephony
+     * layer, since it depends on the underlying telephony technology.
+     *
+     * TODO: Watch out: this is also highly carrier-specific, since the
+     * OTA procedure is different from one carrier to the next, *and* the
+     * different carriers may want very different onscreen UI as well.
+     * The procedure may even be different for different devices with the
+     * same carrier.
+     *
+     * So we eventually will need a much more flexible, pluggable design.
+     * This method here is just a placeholder to reduce hardcoded
+     * "if (CDMA)" checks sprinkled throughout the rest of the phone app.
+     *
+     * TODO: consider using the term "OTASP" rather "OTA" everywhere in the
+     * phone app, since OTA can also mean over-the-air software updates.
+     */
+    /* package */ static boolean supportsOtasp(Phone phone) {
+        return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+    }
+
+    /**
+     * Return true if the current phone can retrieve the voice message count.
+     *
+     * Currently this is assumed to be true on CDMA phones and false otherwise.
+     *
+     * TODO: This capability should really be exposed by the telephony
+     * layer, since it depends on the underlying telephony technology.
+     */
+    /* package */ static boolean supportsVoiceMessageCount(Phone phone) {
+        return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+    }
+
+    /**
+     * Return true if this phone allows the user to select which
+     * network to use.
+     *
+     * Currently this is assumed to be true only on GSM phones.
+     *
+     * TODO: Should CDMA phones allow this as well?
+     */
+    /* package */ static boolean supportsNetworkSelection(Phone phone) {
+        return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+    }
+
+    /**
+     * Returns a resource ID for a label to use when displaying the
+     * "device id" of the current device.  (This is currently used as the
+     * title of the "device id" dialog.)
+     *
+     * This is specific to the device's telephony technology: the device
+     * id is called "IMEI" on GSM phones and "MEID" on CDMA phones.
+     * TODO: ultimately this name should come directly from the
+     * telephony layer.
+     */
+    /* package */ static int getDeviceIdLabel(Phone phone) {
+        if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM) {
+            return R.string.imei;
+        } else if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+            return R.string.meid;
+        } else {
+            Log.w(LOG_TAG, "getDeviceIdLabel: no known label for phone "
+                  + phone.getPhoneName());
+            return 0;
+        }
+    }
+
+    /**
+     * Return true if the current phone supports the ability to explicitly
+     * manage the state of a conference call (i.e. view the participants,
+     * and hangup or separate individual callers.)
+     *
+     * The in-call screen's "Manage conference" UI is available only on
+     * devices that support this feature.
+     *
+     * Currently this is assumed to be true on GSM phones and false otherwise.
+     * TODO: This capability should really be exposed by the telephony
+     * layer, since it depends on the underlying telephony technology.
+     */
+    /* package */ static boolean supportsConferenceCallManagement(Phone phone) {
+        return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+    }
+
+    /**
+     * Return true if the current phone supports explicit "Hold" and
+     * "Unhold" actions for an active call.  (If so, the in-call UI will
+     * provide onscreen "Hold" / "Unhold" buttons.)
+     *
+     * Currently this is assumed to be true on GSM phones and false
+     * otherwise.  (In particular, CDMA has no concept of "putting a call
+     * on hold.")
+     * TODO: This capability should really be exposed by the telephony
+     * layer, since it depends on the underlying telephony technology.
+     */
+    /* package */ static boolean supportsHoldAndUnhold(Phone phone) {
+        return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+    }
+
+    /**
+     * Return true if the current phone supports distinct "Answer & Hold"
+     * and "Answer & End" behaviors in the call-waiting scenario.  If so,
+     * the in-call UI may provide separate buttons or menu items for these
+     * two actions.
+     *
+     * Currently this is assumed to be true on GSM phones and false
+     * otherwise.  (In particular, CDMA has no concept of explicitly
+     * managing the background call, or "putting a call on hold.")
+     *
+     * TODO: This capability should really be exposed by the telephony
+     * layer, since it depends on the underlying telephony technology.
+     *
+     * TODO: It might be better to expose this capability in a more
+     * generic form, like maybe "supportsExplicitMultipleLineManagement()"
+     * rather than focusing specifically on call-waiting behavior.
+     */
+    /* package */ static boolean supportsAnswerAndHold(Phone phone) {
+        return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+    }
+}
diff --git a/phone/src/com/android/phone2/TimeConsumingPreferenceActivity.java b/phone/src/com/android/phone2/TimeConsumingPreferenceActivity.java
index 2918f07..c1abb13 100644
--- a/phone/src/com/android/phone2/TimeConsumingPreferenceActivity.java
+++ b/phone/src/com/android/phone2/TimeConsumingPreferenceActivity.java
@@ -1,5 +1,7 @@
 package com.android.phone2;
 
+import com.android.internal.telephony.CommandException;
+
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.ProgressDialog;
@@ -15,6 +17,7 @@
     public void onStarted(Preference preference, boolean reading);
     public void onFinished(Preference preference, boolean reading);
     public void onError(Preference preference, int error);
+    public void onException(Preference preference, CommandException exception);
 }
 
 public class TimeConsumingPreferenceActivity extends PreferenceActivity
@@ -29,6 +32,7 @@
     static final int EXCEPTION_ERROR = 300;
     static final int RESPONSE_ERROR = 400;
     static final int RADIO_OFF_ERROR = 500;
+    static final int FDN_CHECK_FAILURE = 600;
 
     private final ArrayList<String> mBusyList=new ArrayList<String> ();
 
@@ -55,7 +59,8 @@
             return null;
         }
 
-        if (id == RESPONSE_ERROR || id == RADIO_OFF_ERROR || id == EXCEPTION_ERROR) {
+        if (id == RESPONSE_ERROR || id == RADIO_OFF_ERROR || id == EXCEPTION_ERROR
+                || id == FDN_CHECK_FAILURE) {
             AlertDialog.Builder b = new AlertDialog.Builder(this);
 
             int msgId;
@@ -73,6 +78,11 @@
                     // Set Button 3
                     b.setNeutralButton(R.string.close_dialog, this);
                     break;
+                case FDN_CHECK_FAILURE:
+                    msgId = R.string.fdn_only_error;
+                    // Set Button 2
+                    b.setNegativeButton(R.string.close_dialog, this);
+                    break;
                 case EXCEPTION_ERROR:
                 default:
                     msgId = R.string.exception_error;
@@ -151,6 +161,14 @@
         }
     }
 
+    public void onException(Preference preference, CommandException exception) {
+        if (exception.getCommandError() == CommandException.Error.FDN_CHECK_FAILURE) {
+            onError(preference, FDN_CHECK_FAILURE);
+        } else {
+            preference.setEnabled(false);
+            onError(preference, EXCEPTION_ERROR);
+        }
+    }
     public void onCancel(DialogInterface dialog) {
         if (DBG) dumpState();
         finish();
diff --git a/phone/src/com/android/phone2/Use2GOnlyCheckBoxPreference.java b/phone/src/com/android/phone2/Use2GOnlyCheckBoxPreference.java
index 555b949..aae7410 100644
--- a/phone/src/com/android/phone2/Use2GOnlyCheckBoxPreference.java
+++ b/phone/src/com/android/phone2/Use2GOnlyCheckBoxPreference.java
@@ -25,7 +25,6 @@
 import android.util.Log;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 
 public class Use2GOnlyCheckBoxPreference extends CheckBoxPreference {
     private static final String LOG_TAG = "Use2GOnlyCheckBoxPreference";
@@ -44,7 +43,7 @@
 
     public Use2GOnlyCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone = PhoneApp.getPhone();
         mHandler = new MyHandler();
         mPhone.getPreferredNetworkType(
                 mHandler.obtainMessage(MyHandler.MESSAGE_GET_PREFERRED_NETWORK_TYPE));
diff --git a/phone/src2/com/android/internal/telephony/sip/SipConnection.java b/phone/src2/com/android/internal/telephony/sip/SipConnection.java
index f7abc1f..b66ce2d 100644
--- a/phone/src2/com/android/internal/telephony/sip/SipConnection.java
+++ b/phone/src2/com/android/internal/telephony/sip/SipConnection.java
@@ -637,6 +637,12 @@
         return Connection.PRESENTATION_ALLOWED;
     }
 
+    @Override
+    public UUSInfo getUUSInfo() {
+        // FIXME: what's this for SIP?
+        return null;
+    }
+
     private class MyHandler extends Handler {
         MyHandler(Looper l) {
             super(l);
@@ -651,7 +657,7 @@
                     processNextPostDialChar();
                     break;
                 case EVENT_WAKE_LOCK_TIMEOUT:
-                    releaseWakeLock();
+                    //releaseWakeLock();
                     break;
             }
         }